library(tidyverse)
Warning message:
In `[<-.data.frame`(`*tmp*`, is_list, value = list(`23` = "<S3: blob>")) :
  replacement element 1 has 1 row to replace 0 rows
library(RSQLite)
library(dbplyr)
library(janitor)
library(lubridate)
library(datasets)
library(ggthemes)
library(gganimate)
library(modelr)
library(broom)
library(ggfortify)
library(infer)
library(MASS)
library(tseries)
library(forecast)
library(fable)
library(fabletools)
library(tsibble)
library(tsibbledata)
library(feasts)

1. Data Cleaning

Creating connection to the sqlite database and downloading fires dataset

# Connecting

conn <- dbConnect(SQLite(), "raw_data/FPA_FOD_20170508.sqlite")
# Pulling all the names of the tables in the database file

as.data.frame(dbListTables(conn))
# Making fires dataframe

fires <- tbl(conn, "Fires") %>% collect()

Seeing what other useful information is in the database. The majority are part of the database structure and are not readable in R.

# EPSG worldwide geodetic parameter dataset system
spatial_ref <- tbl(conn, "spatial_ref_sys_all") %>% collect()

# National Wildfire Coordinating Group unit abbreviations 
NWGG <- tbl(conn, "NWCG_UnitIDActive_20170109") %>% collect()
# Disconnect

dbDisconnect(conn)

Selecting columns of interest

fires_small <- fires %>%
  select(NWCG_REPORTING_AGENCY, SOURCE_REPORTING_UNIT_NAME, FIRE_NAME,
         FIRE_YEAR, DISCOVERY_DATE, DISCOVERY_DOY, DISCOVERY_TIME, CONT_DATE,
         CONT_DOY, CONT_TIME, STAT_CAUSE_CODE, STAT_CAUSE_DESCR, FIRE_SIZE, 
         FIRE_SIZE_CLASS, LATITUDE, LONGITUDE, OWNER_CODE, OWNER_DESCR, STATE, 
         COUNTY, FIPS_CODE, FIPS_NAME, Shape)

fires_small <- clean_names(fires_small)

Changing some columms to be factors

fires_small <- fires_small %>%
  mutate(nwcg_reporting_agency = as.factor(nwcg_reporting_agency)) %>%
  mutate(stat_cause_code = as.factor(stat_cause_code)) %>%
  mutate(fire_size_class = as.factor(fire_size_class)) %>%
  mutate(owner_descr = as.factor(owner_descr)) %>%
  mutate(state = as.factor(state)) 

Date is in Julian format, so overwriting with Gregorian format using year and day of year columns. Also adding in a ‘month of year column’ for future use.

fires_small <- fires_small %>%
  mutate(date_origin = as.Date(paste0(fire_year, "-01-01"))) %>%
  mutate(discovery_date = as.Date(discovery_doy, origin = date_origin)) %>%
  mutate(discovery_moy = month(discovery_date, label = TRUE)) %>%
  select(-date_origin)

2. Creating some initial visualisations

Fires per year

year_plot <- fires_small %>%
  group_by(fire_year) %>%
  summarise(num_fires =n())
`summarise()` ungrouping output (override with `.groups` argument)
year_plot %>%
  ggplot +
  aes(x = fire_year, y = num_fires) +
  geom_point() +
  ylim(0, 120000)

  # geom_col(fill = "dark blue", col ="white") +
  # geom_smooth(method = "lm", se = FALSE, colour = "red")

There is a lot of variation in the data between years. Visually it looks like a repeating pattern is occurring every 5 years or so with 4 peaks visible within this reporting period. Having looked at the historic weather for that date range these peaks seems to coincide with recorded heatwaves in 2000, 2006 and 2011.(1)

https://en.wikipedia.org/wiki/List_of_heat_waves

I will try to create a linear model to hopefully show any increase or decrease of fires over time. As this is time series data a linear model will not fit, but it could be interesting to see if it identifies a general underlying trend.

model <- lm(formula = num_fires ~ fire_year, data = year_plot)
summary(model)

Call:
lm(formula = num_fires ~ fire_year, data = year_plot)

Residuals:
   Min     1Q Median     3Q    Max 
-16835  -8688  -2049   9226  34793 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) -609543.8   756667.9  -0.806    0.429
fire_year       343.3      377.7   0.909    0.373

Residual standard error: 12810 on 22 degrees of freedom
Multiple R-squared:  0.03621,   Adjusted R-squared:  -0.007601 
F-statistic: 0.8265 on 1 and 22 DF,  p-value: 0.3731
tidy(model)
clean_names(glance(model))

The R Squared is quite low as expected from the widely spread plot and from the high p value we already know the model is not a good fit

autoplot(model)
`arrange_()` is deprecated as of dplyr 0.7.0.
Please use `arrange()` instead.
See vignette('programming') for more help
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.

The diagnostic plots agree that the model isn’t a great fit and there is likely to be a curve in the best fit line. As this is time series data we already know this is the case.

year_plot %>%
  add_predictions(model) %>%
  add_residuals(model)
year_plot
year_plot %>%
  ggplot(aes(x = fire_year)) +
  geom_point(aes(y = num_fires)) +
  geom_abline(
    intercept = model$coefficients[1],
    slope = model$coefficients[2],
    col = "red"
  ) +
  ylim(0, 120000)

NA

The plotted best fit line does show a slight increase, but as the P value is far too high I can not accept this model as a true representation of the occuring trend

Just to make sure I’m going to use bootstrapping using the same model

bootstrap_distribution_slope <- year_plot %>%
  specify(formula = num_fires ~ fire_year) %>%
  generate(reps = 10000, type = "bootstrap") %>%
  calculate(stat = "slope")

slope_ci95 <- bootstrap_distribution_slope %>%
  get_ci(level = 0.95, type = "percentile")
slope_ci95
bootstrap_distribution_slope %>%
  visualise(bins = 30) +
  shade_ci(endpoints = slope_ci95)

clean_names(tidy(model, conf.int = TRUE, conf.level = 0.95))

As 0 occurs within the 95% confidence intervals of -283 to +1075 it reinforces the fact that this model can not be used to explain if there are any positive or negative trends that are occurring in this data. It will be more use to use a model that is designed for time series and seasonal variations. For that I shall be also requiring more data points so I will now use monthly data and not yearly.

Fires per month

fires_small %>%
  mutate(year_month = make_date(fire_year, discovery_moy)) %>%
  group_by(year_month) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = year_month, y = num_fires) +
  geom_line(col = "dark blue")
`summarise()` ungrouping output (override with `.groups` argument)

Peaks are still shown to be occurring in the summers. The 2006 heatwave is especially visible.

Using the SARIMA model.

monthly <- fires_small %>%
  mutate(year_month = make_date(fire_year, discovery_moy)) %>%
  group_by(year_month) %>%
  summarise(num_fires = n())
`summarise()` ungrouping output (override with `.groups` argument)
write_csv(monthly, path = "clean_data/monthly.csv")

monthly

Continued on seperate worksheet

Fires per day

fires_small %>%
  group_by(discovery_date) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = discovery_date, y = num_fires) +
  geom_line(col = "dark blue") 
`summarise()` ungrouping output (override with `.groups` argument)

This shows a typical time series plot with a cyclic variation due to warmer weather in the summer time.

Fires by day of year

fires_small %>%
  group_by(discovery_doy) %>%
  summarise(num_fires = n()) %>%
  ggplot(aes(x = discovery_doy, y = num_fires)) +
  geom_line(col = "dark blue")
`summarise()` ungrouping output (override with `.groups` argument)

The are peaks around day 60-110 and a big peak around 180.

Checking the data to see where the peak occurs

fires_small %>%
  group_by(discovery_doy) %>%
  summarise(num_fires = n()) %>%
  arrange(desc(num_fires))
`summarise()` ungrouping output (override with `.groups` argument)

The 2 highest days of the year are on 185 and 186, which happens to be Independence Day (4th July) on a normal year and a leap year retrospectively. So I imagine most of the extra fires (literally over double the normal amount) are caused by fireworks.

Fires by month of year

fires_small %>%
  group_by(discovery_moy) %>%
  summarise(num_fires = n()) %>%
  ggplot(aes(x = discovery_moy, y = num_fires)) +
  geom_col(fill = "dark blue", col = "white")
`summarise()` ungrouping output (override with `.groups` argument)

There are 2 definite peaks during the year. March and April are probably due to the US “Spring Break”, where schools and Universities are stopped and so families are likely to be on vacation during that period possibly visiting National Parks. July and August is also Summer Break for school with both families visiting Parks and hot weather likely causes of fire outbreaks.

Fires by cause

options(scipen = 999)

fires_small %>%
  group_by(stat_cause_descr) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(reorder(x = stat_cause_descr, num_fires), y = num_fires) +
  geom_col(fill = "dark blue") + 
  coord_flip() 
`summarise()` ungrouping output (override with `.groups` argument)

Fire avg size by cause

fires_small %>%
  group_by(stat_cause_descr) %>%
  summarise(avg_size = mean(fire_size)) %>%
  ggplot +
  aes(reorder(x = stat_cause_descr, avg_size), y = avg_size) +
  geom_col(fill = "dark blue") + 
  coord_flip()
`summarise()` ungrouping output (override with `.groups` argument)

Avg burn time by cause

fires_small %>%
  summarise(num_na = sum(is.na(cont_date)))

Literally half the data is missing for burn time, making it very difficult to do any meaningful analysis

Fires by size

fires_small %>%
  group_by(fire_size_class) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = fire_size_class, y = num_fires, fill = fire_size_class) +
  geom_col() +
  scale_fill_manual(values = c("red", "orange", "yellow", "green", "blue", 
                               "purple", "black"),
                    name = "Fire Size Classification",
                    breaks = c("A", "B", "C", "D", "E", "F", "G"),
                    labels = c("A: < 1/4 acre", "B: 1/4 to 10 acres", "C: 10 to 100 acres",
                               "D: 100 to 300 acres", "E: 300 to 1000 acres",
                               "F: 1000 to 5000 acres", "G: More than 5000 acres"))
`summarise()` ungrouping output (override with `.groups` argument)

Geo Spatial wrangling

To make it easier to visually detect frequency of wildfires between states I want display it in a map format. As I’m using ggplot2 already I’m going to also use it for maps with the geom_polygon(), coord_map() along with the ggthemes theme_map() functions.

I’m not entirely sure what geo-spatial information is being held with in the sqlite database file, I’ve made a few attempts to retrieve it but have been unsuccessful. Therefore I’m going to utelise the datasets package which includes various bits of information on the US States, including coordinates for state boundaries.

# State boundary co-ordinates from 'datasets' package

state_map <- map_data("state")
state_map

Annoyingly it doesn’t have the abbreviation of the State, only the full name so I need to add that in. Luckily the ‘datasets’ package also has a vector of States names and abbreviations so I shall make a tibble with them both in.

state.abb
 [1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL" "GA" "HI" "ID" "IL" "IN" "IA"
[16] "KS" "KY" "LA" "ME" "MD" "MA" "MI" "MN" "MS" "MO" "MT" "NE" "NV" "NH" "NJ"
[31] "NM" "NY" "NC" "ND" "OH" "OK" "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT" "VT"
[46] "VA" "WA" "WV" "WI" "WY"
state.name
 [1] "Alabama"        "Alaska"         "Arizona"        "Arkansas"      
 [5] "California"     "Colorado"       "Connecticut"    "Delaware"      
 [9] "Florida"        "Georgia"        "Hawaii"         "Idaho"         
[13] "Illinois"       "Indiana"        "Iowa"           "Kansas"        
[17] "Kentucky"       "Louisiana"      "Maine"          "Maryland"      
[21] "Massachusetts"  "Michigan"       "Minnesota"      "Mississippi"   
[25] "Missouri"       "Montana"        "Nebraska"       "Nevada"        
[29] "New Hampshire"  "New Jersey"     "New Mexico"     "New York"      
[33] "North Carolina" "North Dakota"   "Ohio"           "Oklahoma"      
[37] "Oregon"         "Pennsylvania"   "Rhode Island"   "South Carolina"
[41] "South Dakota"   "Tennessee"      "Texas"          "Utah"          
[45] "Vermont"        "Virginia"       "Washington"     "West Virginia" 
[49] "Wisconsin"      "Wyoming"       
state_list <- tibble(state = state.abb, state_name = state.name)
state_list

The state_map dataframe is in lower case and has the column name ‘region’. I shall change the state_list tibble to be the same format so they can be joined together.

state_list <- tibble(state = state.abb, region = tolower(state.name))

Joing state_list to fires_small datasets

fires_states <- fires_small %>%
  left_join(state_list, by = "state")

fires_states

Checking the join has worked and there are no missing values.

fires_states %>%
  filter(is.na(region))

There does seem to be 22,147 NAs in the ‘region’ column we just made. Scrolling through there are 2 missing States of ‘PR’ and ‘DC’ in the states_list tibble.

After some quick research it seems that there are only 50 States in the US. Washington DC is techincally not counted as a state but as a Federal District, as it is the seat of government, so that was why it wasn’t included in the States tibble originally. PR is Puerto Rico and is also not a state but the largest US territory .

I shall add DC and PR into the state_list and re-join it.

# Adding 2 new states

state.abb <- append(state.abb, c("DC", "PR"))
state.name <- append(state.name, c("District of Columbia", "Puerto Rico"))

state_list <- tibble(state = state.abb, region = tolower(state.name))
# Re-joing tibbles

fires_states <- fires_small %>%
  left_join(state_list, by = "state")
# Checking the join has worked properly and there are no NAs

fires_states %>%
  filter(is.na(region))
Warning in `[<-.data.frame`(`*tmp*`, is_list, value = list(`23` = "<S3: blob>")) :
  replacement element 1 has 1 row to replace 0 rows
# Code below brings up a "vector memory exhausted (limit reached?)" error

# fires_joined <- fires_states %>%
#  right_join(state_map, by = "region")

The data set and geo information is too big to join so I’m going to do a summarise first to get the number of fires per region first.

fires_joined <- fires_states %>% 
    select(region) %>%
    group_by(region) %>%
    summarise(num_fires = n()) %>%
    right_join(state_map, by = "region")
`summarise()` ungrouping output (override with `.groups` argument)

Result!! Now doing first geo spatial visualisation

Total Wildfires per state from 1992-2015

fires_joined %>% 
    ggplot +
    (aes(x = long, y = lat, group = group, fill = num_fires)) + 
    geom_polygon() + 
    geom_path(color = "white") + 
    scale_fill_continuous(low = "darkblue", 
                          high = "darkred",
                          name = "Number of fires") + 
    theme_map() + 
    coord_map("mollweide") + 
    ggtitle("Total US Wildfires from 1992-2015") + 
    theme(plot.title = element_text(hjust = 0.5))

3. Geo Spatial Visualisations

The dataset has a cause of fire column so I shall now create some causation plots.

Getting list of fire causes

fires_states %>%
  distinct(stat_cause_descr) %>%
  arrange(-desc(stat_cause_descr))

Total fire by cause in tabular form

fires_states %>%
  select(stat_cause_descr) %>%
  group_by(stat_cause_descr) %>%
  summarise(num_fires = n ()) %>%
  arrange(desc(num_fires))
`summarise()` ungrouping output (override with `.groups` argument)
NA

Number of fires by state in tabular form

fires_states %>%
  select(region) %>%
  group_by(region) %>%
  summarise(num_fires = n()) %>%
  arrange(desc(num_fires))
`summarise()` ungrouping output (override with `.groups` argument)

As the cause needs to be filtered before the map join, I’m going to either going to have to repeat a whole load of the same code in every single plot or write a function that will do it for me with, saving a lot of typing!

# Function for plotting cause of fire

cause <- function(cause) {
  fires_states %>%
    filter(stat_cause_descr == cause) %>%
    select(region) %>%
    group_by(region) %>%
    summarise(num_fires = n ()) %>%
    right_join(state_map, by = "region") %>%
    ggplot +
    (aes(x = long, y = lat, group = group, fill = num_fires)) + 
    geom_polygon() + 
    geom_path(color = "white") + 
    scale_fill_continuous(low = "darkblue", 
                          high = "darkred",
                          name = "Number of fires") + 
    theme_map() + 
    coord_map("mollweide") + 
    ggtitle(paste0("Total US Wildfires caused by ", cause, " from 1992-2015")) + 
    theme(plot.title = element_text(hjust = 0.5))
}

Wildfires caused by Arson

cause("Arson")
`summarise()` ungrouping output (override with `.groups` argument)

Arson does seem more prevalent in the SE states of Mississippi, Georgia, Alabama and also the western state of California.

Wildfires caused by Campfire

cause("Campfire")
`summarise()` ungrouping output (override with `.groups` argument)

Campfires are the most prevalent in the Western states of Oregon, California and Arizona.

Wildfires caused by Children

cause("Children")
`summarise()` ungrouping output (override with `.groups` argument)

Fires by children are spread about the country, but the most prevalent states are California in the West, Alabama and South Carolina and New Jersey in the east.

Wildfires caused by Debris Burning

cause("Debris Burning")
`summarise()` ungrouping output (override with `.groups` argument)

Fires by burning debris are mostly in the southern warmer states of Texas, Georgia and North Carolina.

Wildfires caused by Equiment Use

cause("Equipment Use")
`summarise()` ungrouping output (override with `.groups` argument)

Most of the fires caused by equipment seem to be in California

Wildfires caused by Fireworks

cause("Fireworks")
`summarise()` ungrouping output (override with `.groups` argument)

Most of the fires caused by fireworks seem to be in the north of the country. Primarily South Dakota, Montana and Washington state.

Wildfires caused by Lightning

cause("Lightning")
`summarise()` ungrouping output (override with `.groups` argument)

Apart from a hotspot of lightning strikes in Florida, the vast majority of fires caused by lightning are in the West of the country. With the 3 most affected states being California, Oregon and Arizona.

Wildfires caused by Miscellious

cause("Miscellaneous")
`summarise()` ungrouping output (override with `.groups` argument)

There seems to be quite a few miscellaneous classifications in California, Texas and New York.

Wildfires caused by Missing/Undefined

cause("Missing/Undefined")
`summarise()` ungrouping output (override with `.groups` argument)

The states with the most missing or undefined data is North and South Carolina, Oklahoma and California.

Wildfires caused by Powerline

cause("Powerline")
`summarise()` ungrouping output (override with `.groups` argument)

Texas has the largest amount of wildfires caused by powerlines. This is likely due to the warm climate and the large proportion of the state that is dry grasslands used for agriculture. (1)

  1. https://uk.reuters.com/article/us-wildfires-texas/trees-and-power-lines-caused-major-texas-fire-idUSTRE78J76A20110920

Wildfires caused by Railroad

cause("Railroad")
`summarise()` ungrouping output (override with `.groups` argument)

By far Florida has the most wildfires caused by railroads.

Wildfires caused by Smoking

cause("Smoking")
`summarise()` ungrouping output (override with `.groups` argument)

Fires caused by smoking seem to be spread around the country, but mainly on the east and west coasts.

Wildfires caused by Structure

cause("Structure")
`summarise()` ungrouping output (override with `.groups` argument)

South Dakota has the largest proportion of fires caused by structures.

Unsurprisingly the southern states seem to have more occurences of wildifre in general, no doubt due to the warmer climate at their latitudes. Also the 1st and 3rd states with the highest number of fires are also the 2 largest States by size. However the 2nd highest State is Georgia, which although it is in the South of the country is only an average sized State. Therefore to get a better picture of what is going on I’m going to look at the proportion of fires occuring by square mile by normalising the State size.

The dataset package also has the area in square miles of each state included in the state.area vector.

state.area
 [1]  51609 589757 113909  53104 158693 104247   5009   2057  58560  58876
[11]   6450  83557  56400  36291  56290  82264  40395  48523  33215  10577
[21]   8257  58216  84068  47716  69686 147138  77227 110540   9304   7836
[31] 121666  49576  52586  70665  41222  69919  96981  45333   1214  31055
[41]  77047  42244 267339  84916   9609  40815  68192  24181  56154  97914
length(state.area)
[1] 50

Annoyingly it also only has 50 states not 52 so I will need to add in DC and PR back in.

(Area figures obtained from Wikipedia)

DC = 68 miles^2 PR = 3515 miles^2

# To make my life easier I'm going to remove the state.abb and .name files and make the tibble again, adding in the land area figures at the same time to make sure they are in the correct order.

rm(state.abb)
rm(state.name)

state.abb <- append(state.abb, c("DC", "PR"))
state.name <- append(state.name, c("District of Columbia", "Puerto Rico"))
state.area <- append(state.area, c("68", "3515"))

state_list <- tibble(state = state.abb, region = tolower(state.name), area = as.numeric(state.area))
# Re-joining tibbles

fires_states <- fires_small %>%
  left_join(state_list, by = "state")

Normalising States area sizes

fires_states %>%
  select(region, area) %>%
  group_by(region, area) %>%
  summarise(num_fires = n()) %>%
  mutate(fires_sqmile = num_fires / area) %>%
  arrange(desc(fires_sqmile))
`summarise()` regrouping output by 'region' (override with `.groups` argument)

This table shows Puerto Rico has the highest proportion of fires compared to its size, followed by New Jersey in the NE of the country and finally by the States in the SE of the country.

fires_states %>%
  select(region, area) %>%
  group_by(region, area) %>%
  summarise(num_fires = n()) %>%
  mutate(fires_sqmile = num_fires / area) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = fires_sqmile)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  scale_fill_distiller(name = "Fire per Sq Mile", palette = "PuBuGn") +
  theme_map() + 
  coord_map("mollweide") + 
  ggtitle(paste0("Total US Wildfires per Square Mile from 1992-2015")) + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)

Puerto Rico is not shown on this map, but visually we can see the data for the other 51 entries, and the south eastern states still have the highest proportion of wildfires. Interestingly New Jersey also shows has a hotspot in the NE of the country.

Do causes change over time?

Splitting causes into 2 group for legibility.

The first group is for directly man created fires.

fires_states %>%
  select(stat_cause_descr, fire_year) %>%
  group_by(fire_year, stat_cause_descr) %>%
  filter(stat_cause_descr == "Arson" | stat_cause_descr == "Campfire" |
           stat_cause_descr == "Children" | stat_cause_descr == "Equipment Use" |
           stat_cause_descr == "Fireworks" | stat_cause_descr == "Smoking") %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = fire_year, y = num_fires, colour = stat_cause_descr) +
  geom_line()
`summarise()` regrouping output by 'fire_year' (override with `.groups` argument)

The 2 large peaks in Arson are obvious in 1999 and 2006. There was a large heatwave in 2006, but I’m not sure why this would result in an increase in arson. Unless this was just due to the dry ground creating extra fuel to aid the spread of fires that would have normally not resulted in a large scale fire. This may also be the same reason that there is also another peak in 2006 for Equipment Use. Arson however does look to be decreasing since 2006.

And this one for natural occuring fires.

fires_states %>%
  select(stat_cause_descr, fire_year) %>%
  group_by(fire_year, stat_cause_descr) %>%
  filter(stat_cause_descr == "Debris Burning" | stat_cause_descr == "Lightning" |
           stat_cause_descr == "Miscellaneous" | stat_cause_descr == 
           "Missing/Undefined" | stat_cause_descr == "Powerline" | 
           stat_cause_descr == "Railroad" | stat_cause_descr == "Structure") %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = fire_year, y = num_fires, colour = stat_cause_descr) +
  geom_line()
`summarise()` regrouping output by 'fire_year' (override with `.groups` argument)

Similar peaks can be seen in Debris, Miscellaneous and lightning in the heatwave of 2006 that left the ground very dry. There are peaks from 1997 to 2003 in debris, miscellaneous and lightening, but also a trough in missing/undefined, so this is likely to be due to more accurate classification of fires and not using the missing/undefined category as much.

Difference in causes between states

state_map_southern <- state_map %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" | 
           region == "arkansas" | region == "louisiana")
fires_states %>%
  filter(fire_year == "1992" | fire_year == "1993" | fire_year == "1994" |
           fire_year == "1995") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 1992-1995") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "1996" | fire_year == "1997" | fire_year == "1998" |
           fire_year == "1999") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 1996-1999") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2000" | fire_year == "2001" | fire_year == "2002" |
           fire_year == "2003") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2000-2003") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2004" | fire_year == "2005" | fire_year == "2006" |
           fire_year == "2007") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2004-2007") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2008" | fire_year == "2009" | fire_year == "2010" |
           fire_year == "2011") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2008-2011") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2012" | fire_year == "2013" | fire_year == "2014" |
           fire_year == "2015") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2012-2015") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

Looking at these trends some interesting insights can be seen. For the combined years data Florida stands out as having railroad as its main cause of wildfire, but from the above plots it can be seen that these railroad fires are only the main cause up to the 4 yearly period ending in 2003 and then the main cause changes to lightning until the end of the collection period in 2015. Similarly arson seem reasonably popular in the southern states until 2007, when it no longer appears as the most common cause of wildfire. This downward trend was also noted earlier in the overall causation plots for all states

Correlation between states and fire size

fires_states %>%
  select(region, fire_size_class) %>%
  group_by(region, fire_size_class) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = fire_size_class)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Fire Size Class", palette = "PuBuGn") +
  ggtitle("Most common wildfire size per State 1992-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  select(region, fire_size_class) %>%
  filter(fire_size_class == "G") %>%
  group_by(region) %>%
  summarise(num_fire = n()) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = num_fire)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_distiller(name = "Number of Fires", palette = "PuBuGn") +
  ggtitle("Number of large class G fires per State 1992-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

From the plots we can see that the Western states have the most small fires and also the most large fires! Not entirely the most helpful plots…

Are fires more prevalent in certain months for individual states

fires_states %>%
  filter(fire_year == "1992" | fire_year == "1993" | fire_year == "1994" |
           fire_year == "1995") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 1992-1995") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "1996" | fire_year == "1997" | fire_year == "1998" |
           fire_year == "1999") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 1996-1999") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2000" | fire_year == "2001" | fire_year == "2002" |
           fire_year == "2003") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2000-2003") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2004" | fire_year == "2005" | fire_year == "2006" |
           fire_year == "2007") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2004-2007") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2008" | fire_year == "2009" | fire_year == "2010" |
           fire_year == "2011") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2008-2011") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2012" | fire_year == "2013" | fire_year == "2014" |
           fire_year == "2015") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2012-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2010" | fire_year == "2011" | fire_year == "2012" |
           fire_year == "2013" | fire_year == "2014" | fire_year == "2015") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires in per State 2010-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

The above plots are quite interesting. The months of the year that have the most seems to widely change in certain state. Mainly the east half of the country have the most fires in the Spring (Feb-May) and the western part of the country have the most fires later on in Summer and Fall (Jun-Oct). There are however a few exceptions that can be seen in the 2004-2007 and 2008-2011 data Texas has the most fires in January. Florida also mostly conformed to the East/West split with the majority of its worst months for fires taking place in March or April up until 2007, then the most common month moves later into June and July for the rest of the reporting period until 2015. This may have to due with main cause of fires in Florida changing from railroad to lightning related about the same time, as we noted earlier on when looking at causation. As July is the main month for tropical storms and lightning in Florida this is a possible cause for the highest month becoming later in the year than before. (2)

  1. https://www.weather.gov/mlb/fl_lightning_climo
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KFJTUUxpdGUpCmxpYnJhcnkoZGJwbHlyKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGRhdGFzZXRzKQpsaWJyYXJ5KGdndGhlbWVzKQpsaWJyYXJ5KGdnYW5pbWF0ZSkKbGlicmFyeShtb2RlbHIpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkoZ2dmb3J0aWZ5KQpsaWJyYXJ5KGluZmVyKQpsaWJyYXJ5KE1BU1MpCmxpYnJhcnkodHNlcmllcykKbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeShmYWJsZSkKbGlicmFyeShmYWJsZXRvb2xzKQpsaWJyYXJ5KHRzaWJibGUpCmxpYnJhcnkodHNpYmJsZWRhdGEpCmxpYnJhcnkoZmVhc3RzKQpgYGAKCgojIDEuICBEYXRhIENsZWFuaW5nCgoKIyMjIyAgQ3JlYXRpbmcgY29ubmVjdGlvbiB0byB0aGUgc3FsaXRlIGRhdGFiYXNlIGFuZCBkb3dubG9hZGluZyBmaXJlcyBkYXRhc2V0CgpgYGB7cn0KIyBDb25uZWN0aW5nCgpjb25uIDwtIGRiQ29ubmVjdChTUUxpdGUoKSwgInJhd19kYXRhL0ZQQV9GT0RfMjAxNzA1MDguc3FsaXRlIikKYGBgCgpgYGB7cn0KIyBQdWxsaW5nIGFsbCB0aGUgbmFtZXMgb2YgdGhlIHRhYmxlcyBpbiB0aGUgZGF0YWJhc2UgZmlsZQoKYXMuZGF0YS5mcmFtZShkYkxpc3RUYWJsZXMoY29ubikpCmBgYAoKYGBge3J9CiMgTWFraW5nIGZpcmVzIGRhdGFmcmFtZQoKZmlyZXMgPC0gdGJsKGNvbm4sICJGaXJlcyIpICU+JSBjb2xsZWN0KCkKYGBgCgoKIyMjIyBTZWVpbmcgd2hhdCBvdGhlciB1c2VmdWwgaW5mb3JtYXRpb24gaXMgaW4gdGhlIGRhdGFiYXNlLiAgVGhlIG1ham9yaXR5IGFyZSBwYXJ0IG9mIHRoZSBkYXRhYmFzZSBzdHJ1Y3R1cmUgYW5kIGFyZSBub3QgcmVhZGFibGUgaW4gUi4KCmBgYHtyfQojIEVQU0cgd29ybGR3aWRlIGdlb2RldGljIHBhcmFtZXRlciBkYXRhc2V0IHN5c3RlbQpzcGF0aWFsX3JlZiA8LSB0YmwoY29ubiwgInNwYXRpYWxfcmVmX3N5c19hbGwiKSAlPiUgY29sbGVjdCgpCgojIE5hdGlvbmFsIFdpbGRmaXJlIENvb3JkaW5hdGluZyBHcm91cCB1bml0IGFiYnJldmlhdGlvbnMgCk5XR0cgPC0gdGJsKGNvbm4sICJOV0NHX1VuaXRJREFjdGl2ZV8yMDE3MDEwOSIpICU+JSBjb2xsZWN0KCkKYGBgCgoKYGBge3J9CiMgRGlzY29ubmVjdAoKZGJEaXNjb25uZWN0KGNvbm4pCmBgYAoKCiMjIyBTZWxlY3RpbmcgY29sdW1ucyBvZiBpbnRlcmVzdAoKYGBge3J9CmZpcmVzX3NtYWxsIDwtIGZpcmVzICU+JQogIHNlbGVjdChOV0NHX1JFUE9SVElOR19BR0VOQ1ksIFNPVVJDRV9SRVBPUlRJTkdfVU5JVF9OQU1FLCBGSVJFX05BTUUsCiAgICAgICAgIEZJUkVfWUVBUiwgRElTQ09WRVJZX0RBVEUsIERJU0NPVkVSWV9ET1ksIERJU0NPVkVSWV9USU1FLCBDT05UX0RBVEUsCiAgICAgICAgIENPTlRfRE9ZLCBDT05UX1RJTUUsIFNUQVRfQ0FVU0VfQ09ERSwgU1RBVF9DQVVTRV9ERVNDUiwgRklSRV9TSVpFLCAKICAgICAgICAgRklSRV9TSVpFX0NMQVNTLCBMQVRJVFVERSwgTE9OR0lUVURFLCBPV05FUl9DT0RFLCBPV05FUl9ERVNDUiwgU1RBVEUsIAogICAgICAgICBDT1VOVFksIEZJUFNfQ09ERSwgRklQU19OQU1FLCBTaGFwZSkKCmZpcmVzX3NtYWxsIDwtIGNsZWFuX25hbWVzKGZpcmVzX3NtYWxsKQpgYGAKCgojIyMgQ2hhbmdpbmcgc29tZSBjb2x1bW1zIHRvIGJlIGZhY3RvcnMKCmBgYHtyfQpmaXJlc19zbWFsbCA8LSBmaXJlc19zbWFsbCAlPiUKICBtdXRhdGUobndjZ19yZXBvcnRpbmdfYWdlbmN5ID0gYXMuZmFjdG9yKG53Y2dfcmVwb3J0aW5nX2FnZW5jeSkpICU+JQogIG11dGF0ZShzdGF0X2NhdXNlX2NvZGUgPSBhcy5mYWN0b3Ioc3RhdF9jYXVzZV9jb2RlKSkgJT4lCiAgbXV0YXRlKGZpcmVfc2l6ZV9jbGFzcyA9IGFzLmZhY3RvcihmaXJlX3NpemVfY2xhc3MpKSAlPiUKICBtdXRhdGUob3duZXJfZGVzY3IgPSBhcy5mYWN0b3Iob3duZXJfZGVzY3IpKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBhcy5mYWN0b3Ioc3RhdGUpKSAKYGBgCgoKIyMjIERhdGUgaXMgaW4gSnVsaWFuIGZvcm1hdCwgc28gb3ZlcndyaXRpbmcgd2l0aCBHcmVnb3JpYW4gZm9ybWF0IHVzaW5nIHllYXIgYW5kIGRheSBvZiB5ZWFyIGNvbHVtbnMuICBBbHNvIGFkZGluZyBpbiBhICdtb250aCBvZiB5ZWFyIGNvbHVtbicgZm9yIGZ1dHVyZSB1c2UuCgpgYGB7cn0KZmlyZXNfc21hbGwgPC0gZmlyZXNfc21hbGwgJT4lCiAgbXV0YXRlKGRhdGVfb3JpZ2luID0gYXMuRGF0ZShwYXN0ZTAoZmlyZV95ZWFyLCAiLTAxLTAxIikpKSAlPiUKICBtdXRhdGUoZGlzY292ZXJ5X2RhdGUgPSBhcy5EYXRlKGRpc2NvdmVyeV9kb3ksIG9yaWdpbiA9IGRhdGVfb3JpZ2luKSkgJT4lCiAgbXV0YXRlKGRpc2NvdmVyeV9tb3kgPSBtb250aChkaXNjb3ZlcnlfZGF0ZSwgbGFiZWwgPSBUUlVFKSkgJT4lCiAgc2VsZWN0KC1kYXRlX29yaWdpbikKYGBgCgoKCiMgMi4gQ3JlYXRpbmcgc29tZSBpbml0aWFsIHZpc3VhbGlzYXRpb25zCgoKIyMjIEZpcmVzIHBlciB5ZWFyCgpgYGB7cn0KeWVhcl9wbG90IDwtIGZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KGZpcmVfeWVhcikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9bigpKQoKeWVhcl9wbG90ICU+JQogIGdncGxvdCArCiAgYWVzKHggPSBmaXJlX3llYXIsIHkgPSBudW1fZmlyZXMpICsKICBnZW9tX3BvaW50KCkgKwogIHlsaW0oMCwgMTIwMDAwKQoKYGBgCioqVGhlcmUgaXMgYSBsb3Qgb2YgdmFyaWF0aW9uIGluIHRoZSBkYXRhIGJldHdlZW4geWVhcnMuICBWaXN1YWxseSBpdCBsb29rcyBsaWtlIGEgcmVwZWF0aW5nIHBhdHRlcm4gaXMgb2NjdXJyaW5nIGV2ZXJ5IDUgeWVhcnMgb3Igc28gd2l0aCA0IHBlYWtzIHZpc2libGUgd2l0aGluIHRoaXMgcmVwb3J0aW5nIHBlcmlvZC4gIEhhdmluZyBsb29rZWQgYXQgdGhlIGhpc3RvcmljIHdlYXRoZXIgZm9yIHRoYXQgZGF0ZSByYW5nZSB0aGVzZSBwZWFrcyBzZWVtcyB0byBjb2luY2lkZSB3aXRoIHJlY29yZGVkIGhlYXR3YXZlcyBpbiAyMDAwLCAyMDA2IGFuZCAyMDExLigxKSoqCgpodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX2hlYXRfd2F2ZXMKCgojIyMjIEkgd2lsbCB0cnkgdG8gY3JlYXRlIGEgbGluZWFyIG1vZGVsIHRvIGhvcGVmdWxseSBzaG93IGFueSBpbmNyZWFzZSBvciBkZWNyZWFzZSBvZiBmaXJlcyBvdmVyIHRpbWUuICBBcyB0aGlzIGlzIHRpbWUgc2VyaWVzIGRhdGEgYSBsaW5lYXIgbW9kZWwgd2lsbCBub3QgZml0LCBidXQgaXQgY291bGQgYmUgaW50ZXJlc3RpbmcgdG8gc2VlIGlmIGl0IGlkZW50aWZpZXMgYSBnZW5lcmFsIHVuZGVybHlpbmcgdHJlbmQuCgoKYGBge3J9CiMgY3JlYXRpbmcgdGhlIGxpbmVhciBtb2RlbAoKbW9kZWwgPC0gbG0oZm9ybXVsYSA9IG51bV9maXJlcyB+IGZpcmVfeWVhciwgZGF0YSA9IHllYXJfcGxvdCkKc3VtbWFyeShtb2RlbCkKYGBgCmBgYHtyfQp0aWR5KG1vZGVsKQpgYGAKCmBgYHtyfQpjbGVhbl9uYW1lcyhnbGFuY2UobW9kZWwpKQpgYGAKCioqVGhlIFIgU3F1YXJlZCBpcyBxdWl0ZSBsb3cgYXMgZXhwZWN0ZWQgZnJvbSB0aGUgd2lkZWx5IHNwcmVhZCBwbG90IGFuZCBmcm9tIHRoZSBoaWdoIHAgdmFsdWUgd2UgYWxyZWFkeSBrbm93IHRoZSBtb2RlbCBpcyBub3QgYSBnb29kIGZpdCoqCgoKYGBge3J9CiMgZGlhZ25vc3RpYyBwbG90cwoKYXV0b3Bsb3QobW9kZWwpCmBgYAoKKipUaGUgZGlhZ25vc3RpYyBwbG90cyBhZ3JlZSB0aGF0IHRoZSBtb2RlbCBpc24ndCBhIGdyZWF0IGZpdCBhbmQgdGhlcmUgaXMgbGlrZWx5IHRvIGJlIGEgY3VydmUgaW4gdGhlIGJlc3QgZml0IGxpbmUuICBBcyB0aGlzIGlzIHRpbWUgc2VyaWVzIGRhdGEgd2UgYWxyZWFkeSBrbm93IHRoaXMgaXMgdGhlIGNhc2UuKioKCgpgYGB7cn0KeWVhcl9wbG90ICU+JQogIGFkZF9wcmVkaWN0aW9ucyhtb2RlbCkgJT4lCiAgYWRkX3Jlc2lkdWFscyhtb2RlbCkKeWVhcl9wbG90CmBgYAoKYGBge3J9CiMgcGxvdHRpbmcgdGhlIG1vZGVsIGJlc3QgZml0IGxpbmUKCnllYXJfcGxvdCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBmaXJlX3llYXIpKSArCiAgZ2VvbV9wb2ludChhZXMoeSA9IG51bV9maXJlcykpICsKICBnZW9tX2FibGluZSgKICAgIGludGVyY2VwdCA9IG1vZGVsJGNvZWZmaWNpZW50c1sxXSwKICAgIHNsb3BlID0gbW9kZWwkY29lZmZpY2llbnRzWzJdLAogICAgY29sID0gInJlZCIKICApICsKICB5bGltKDAsIDEyMDAwMCkKICAKYGBgCgoqKlRoZSBwbG90dGVkIGJlc3QgZml0IGxpbmUgZG9lcyBzaG93IGEgc2xpZ2h0IGluY3JlYXNlLCBidXQgYXMgdGhlIFAgdmFsdWUgaXMgZmFyIHRvbyBoaWdoIEkgY2FuIG5vdCBhY2NlcHQgdGhpcyBtb2RlbCBhcyBhIHRydWUgcmVwcmVzZW50YXRpb24gb2YgdGhlIG9jY3VyaW5nIHRyZW5kKioKCgojIyMgSnVzdCB0byBtYWtlIHN1cmUgSSdtIGdvaW5nIHRvIHVzZSBib290c3RyYXBwaW5nIHVzaW5nIHRoZSBzYW1lIG1vZGVsCgoKYGBge3J9CmJvb3RzdHJhcF9kaXN0cmlidXRpb25fc2xvcGUgPC0geWVhcl9wbG90ICU+JQogIHNwZWNpZnkoZm9ybXVsYSA9IG51bV9maXJlcyB+IGZpcmVfeWVhcikgJT4lCiAgZ2VuZXJhdGUocmVwcyA9IDEwMDAwLCB0eXBlID0gImJvb3RzdHJhcCIpICU+JQogIGNhbGN1bGF0ZShzdGF0ID0gInNsb3BlIikKCnNsb3BlX2NpOTUgPC0gYm9vdHN0cmFwX2Rpc3RyaWJ1dGlvbl9zbG9wZSAlPiUKICBnZXRfY2kobGV2ZWwgPSAwLjk1LCB0eXBlID0gInBlcmNlbnRpbGUiKQpzbG9wZV9jaTk1CmBgYAoKYGBge3J9CmJvb3RzdHJhcF9kaXN0cmlidXRpb25fc2xvcGUgJT4lCiAgdmlzdWFsaXNlKGJpbnMgPSAzMCkgKwogIHNoYWRlX2NpKGVuZHBvaW50cyA9IHNsb3BlX2NpOTUpCmBgYAoKYGBge3J9CmNsZWFuX25hbWVzKHRpZHkobW9kZWwsIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTUpKQpgYGAKCioqQXMgMCBvY2N1cnMgd2l0aGluIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgLTI4MyB0byArMTA3NSBpdCByZWluZm9yY2VzIHRoZSBmYWN0IHRoYXQgdGhpcyBtb2RlbCBjYW4gbm90IGJlIHVzZWQgdG8gZXhwbGFpbiBpZiB0aGVyZSBhcmUgYW55IHBvc2l0aXZlIG9yIG5lZ2F0aXZlIHRyZW5kcyB0aGF0IGFyZSBvY2N1cnJpbmcgaW4gdGhpcyBkYXRhLiAgSXQgd2lsbCBiZSBtb3JlIHVzZSB0byB1c2UgYSBtb2RlbCB0aGF0IGlzIGRlc2lnbmVkIGZvciB0aW1lIHNlcmllcyBhbmQgc2Vhc29uYWwgdmFyaWF0aW9ucy4gIEZvciB0aGF0IEkgc2hhbGwgYmUgYWxzbyByZXF1aXJpbmcgbW9yZSBkYXRhIHBvaW50cyBzbyBJIHdpbGwgbm93IHVzZSBtb250aGx5IGRhdGEgYW5kIG5vdCB5ZWFybHkuKioKCgoKIyMjIEZpcmVzIHBlciBtb250aAoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIG11dGF0ZSh5ZWFyX21vbnRoID0gbWFrZV9kYXRlKGZpcmVfeWVhciwgZGlzY292ZXJ5X21veSkpICU+JQogIGdyb3VwX2J5KHllYXJfbW9udGgpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpICU+JQogIGdncGxvdCArCiAgYWVzKHggPSB5ZWFyX21vbnRoLCB5ID0gbnVtX2ZpcmVzKSArCiAgZ2VvbV9saW5lKGNvbCA9ICJkYXJrIGJsdWUiKQpgYGAKCioqUGVha3MgYXJlIHN0aWxsIHNob3duIHRvIGJlIG9jY3VycmluZyBpbiB0aGUgc3VtbWVycy4gVGhlIDIwMDYgaGVhdHdhdmUgaXMgZXNwZWNpYWxseSB2aXNpYmxlLioqCgoKCiMjIyBVc2luZyB0aGUgU0FSSU1BIG1vZGVsLgoKYGBge3J9Cm1vbnRobHkgPC0gZmlyZXNfc21hbGwgJT4lCiAgbXV0YXRlKHllYXJfbW9udGggPSBtYWtlX2RhdGUoZmlyZV95ZWFyLCBkaXNjb3ZlcnlfbW95KSkgJT4lCiAgZ3JvdXBfYnkoeWVhcl9tb250aCkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkKCndyaXRlX2Nzdihtb250aGx5LCBwYXRoID0gImNsZWFuX2RhdGEvbW9udGhseS5jc3YiKQoKbW9udGhseQpgYGAKCioqQ29udGludWVkIG9uIHNlcGVyYXRlIHdvcmtzaGVldCoqCgoKCgojIyMgRmlyZXMgcGVyIGRheQoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KGRpc2NvdmVyeV9kYXRlKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBnZ3Bsb3QgKwogIGFlcyh4ID0gZGlzY292ZXJ5X2RhdGUsIHkgPSBudW1fZmlyZXMpICsKICBnZW9tX2xpbmUoY29sID0gImRhcmsgYmx1ZSIpIAoKYGBgCgoqKlRoaXMgc2hvd3MgYSB0eXBpY2FsIHRpbWUgc2VyaWVzIHBsb3Qgd2l0aCBhIGN5Y2xpYyB2YXJpYXRpb24gZHVlIHRvIHdhcm1lciB3ZWF0aGVyIGluIHRoZSBzdW1tZXIgdGltZS4qKgoKCgoKCiMjIyBGaXJlcyBieSBkYXkgb2YgeWVhcgoKCmBgYHtyfQpmaXJlc19zbWFsbCAlPiUKICBncm91cF9ieShkaXNjb3ZlcnlfZG95KSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkaXNjb3ZlcnlfZG95LCB5ID0gbnVtX2ZpcmVzKSkgKwogIGdlb21fbGluZShjb2wgPSAiZGFyayBibHVlIikKYGBgCgoKKipUaGUgYXJlIHBlYWtzIGFyb3VuZCBkYXkgNjAtMTEwIGFuZCBhIGJpZyBwZWFrIGFyb3VuZCAxODAuKioKCiMjIyMgQ2hlY2tpbmcgdGhlIGRhdGEgdG8gc2VlIHdoZXJlIHRoZSBwZWFrIG9jY3VycwoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KGRpc2NvdmVyeV9kb3kpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhudW1fZmlyZXMpKQpgYGAKKipUaGUgMiBoaWdoZXN0IGRheXMgb2YgdGhlIHllYXIgYXJlIG9uIDE4NSBhbmQgMTg2LCB3aGljaCBoYXBwZW5zIHRvIGJlIEluZGVwZW5kZW5jZSBEYXkgKDR0aCBKdWx5KSBvbiBhIG5vcm1hbCB5ZWFyIGFuZCBhIGxlYXAgeWVhciByZXRyb3NwZWN0aXZlbHkuICBTbyBJIGltYWdpbmUgbW9zdCBvZiB0aGUgZXh0cmEgZmlyZXMgKGxpdGVyYWxseSBvdmVyIGRvdWJsZSB0aGUgbm9ybWFsIGFtb3VudCkgYXJlIGNhdXNlZCBieSBmaXJld29ya3MuKioKCgoKIyMjIEZpcmVzIGJ5IG1vbnRoIG9mIHllYXIKCmBgYHtyfQpmaXJlc19zbWFsbCAlPiUKICBncm91cF9ieShkaXNjb3ZlcnlfbW95KSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkaXNjb3ZlcnlfbW95LCB5ID0gbnVtX2ZpcmVzKSkgKwogIGdlb21fY29sKGZpbGwgPSAiZGFyayBibHVlIiwgY29sID0gIndoaXRlIikKYGBgCgoqKlRoZXJlIGFyZSAyIGRlZmluaXRlIHBlYWtzIGR1cmluZyB0aGUgeWVhci4gIE1hcmNoIGFuZCBBcHJpbCBhcmUgcHJvYmFibHkgZHVlIHRvIHRoZSBVUyAiU3ByaW5nIEJyZWFrIiwgd2hlcmUgc2Nob29scyBhbmQgVW5pdmVyc2l0aWVzIGFyZSBzdG9wcGVkIGFuZCBzbyBmYW1pbGllcyBhcmUgbGlrZWx5IHRvIGJlIG9uIHZhY2F0aW9uIGR1cmluZyB0aGF0IHBlcmlvZCBwb3NzaWJseSB2aXNpdGluZyBOYXRpb25hbCBQYXJrcy4gIEp1bHkgYW5kIEF1Z3VzdCBpcyBhbHNvIFN1bW1lciBCcmVhayBmb3Igc2Nob29sIHdpdGggYm90aCBmYW1pbGllcyB2aXNpdGluZyBQYXJrcyBhbmQgaG90IHdlYXRoZXIgbGlrZWx5IGNhdXNlcyBvZiBmaXJlIG91dGJyZWFrcy4qKgoKCgoKIyMjIEZpcmVzIGJ5IGNhdXNlCgpgYGB7cn0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpCgpmaXJlc19zbWFsbCAlPiUKICBncm91cF9ieShzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBnZ3Bsb3QgKwogIGFlcyhyZW9yZGVyKHggPSBzdGF0X2NhdXNlX2Rlc2NyLCBudW1fZmlyZXMpLCB5ID0gbnVtX2ZpcmVzKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJkYXJrIGJsdWUiKSArIAogIGNvb3JkX2ZsaXAoKSAKYGBgCgoKIyMjIEZpcmUgYXZnIHNpemUgYnkgY2F1c2UKCmBgYHtyfQpmaXJlc19zbWFsbCAlPiUKICBncm91cF9ieShzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UoYXZnX3NpemUgPSBtZWFuKGZpcmVfc2l6ZSkpICU+JQogIGdncGxvdCArCiAgYWVzKHJlb3JkZXIoeCA9IHN0YXRfY2F1c2VfZGVzY3IsIGF2Z19zaXplKSwgeSA9IGF2Z19zaXplKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJkYXJrIGJsdWUiKSArIAogIGNvb3JkX2ZsaXAoKQpgYGAKCgojIyMgQXZnIGJ1cm4gdGltZSBieSBjYXVzZQoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIHN1bW1hcmlzZShudW1fbmEgPSBzdW0oaXMubmEoY29udF9kYXRlKSkpCmBgYAoqTGl0ZXJhbGx5IGhhbGYgdGhlIGRhdGEgaXMgbWlzc2luZyBmb3IgYnVybiB0aW1lLCBtYWtpbmcgaXQgdmVyeSBkaWZmaWN1bHQgdG8gZG8gYW55IG1lYW5pbmdmdWwgYW5hbHlzaXMqCgoKCiMjIyBGaXJlcyBieSBzaXplCgoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KGZpcmVfc2l6ZV9jbGFzcykgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgZ2dwbG90ICsKICBhZXMoeCA9IGZpcmVfc2l6ZV9jbGFzcywgeSA9IG51bV9maXJlcywgZmlsbCA9IGZpcmVfc2l6ZV9jbGFzcykgKwogIGdlb21fY29sKCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJvcmFuZ2UiLCAieWVsbG93IiwgImdyZWVuIiwgImJsdWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwdXJwbGUiLCAiYmxhY2siKSwKICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkZpcmUgU2l6ZSBDbGFzc2lmaWNhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkE6IDwgMS80IGFjcmUiLCAiQjogMS80IHRvIDEwIGFjcmVzIiwgIkM6IDEwIHRvIDEwMCBhY3JlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRDogMTAwIHRvIDMwMCBhY3JlcyIsICJFOiAzMDAgdG8gMTAwMCBhY3JlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRjogMTAwMCB0byA1MDAwIGFjcmVzIiwgIkc6IE1vcmUgdGhhbiA1MDAwIGFjcmVzIikpCgpgYGAKCgoKIyBHZW8gU3BhdGlhbCB3cmFuZ2xpbmcgCgoKIyMjIFRvIG1ha2UgaXQgZWFzaWVyIHRvIHZpc3VhbGx5IGRldGVjdCBmcmVxdWVuY3kgb2Ygd2lsZGZpcmVzIGJldHdlZW4gc3RhdGVzIEkgd2FudCBkaXNwbGF5IGl0IGluIGEgbWFwIGZvcm1hdC4gIEFzIEknbSB1c2luZyBnZ3Bsb3QyIGFscmVhZHkgSSdtIGdvaW5nIHRvIGFsc28gdXNlIGl0IGZvciBtYXBzIHdpdGggdGhlIGBnZW9tX3BvbHlnb24oKWAsIGBjb29yZF9tYXAoKWAgYWxvbmcgd2l0aCB0aGUgZ2d0aGVtZXMgYHRoZW1lX21hcCgpYCBmdW5jdGlvbnMuCgoKIyMjIyBJJ20gbm90IGVudGlyZWx5IHN1cmUgd2hhdCBnZW8tc3BhdGlhbCBpbmZvcm1hdGlvbiBpcyBiZWluZyBoZWxkIHdpdGggaW4gdGhlIHNxbGl0ZSBkYXRhYmFzZSBmaWxlLCBJJ3ZlIG1hZGUgYSBmZXcgYXR0ZW1wdHMgdG8gcmV0cmlldmUgaXQgYnV0IGhhdmUgYmVlbiB1bnN1Y2Nlc3NmdWwuICBUaGVyZWZvcmUgSSdtIGdvaW5nIHRvIHV0ZWxpc2UgdGhlIGBkYXRhc2V0c2AgcGFja2FnZSB3aGljaCBpbmNsdWRlcyB2YXJpb3VzIGJpdHMgb2YgaW5mb3JtYXRpb24gb24gdGhlIFVTIFN0YXRlcywgaW5jbHVkaW5nIGNvb3JkaW5hdGVzIGZvciBzdGF0ZSBib3VuZGFyaWVzLgoKCmBgYHtyfQojIFN0YXRlIGJvdW5kYXJ5IGNvLW9yZGluYXRlcyBmcm9tICdkYXRhc2V0cycgcGFja2FnZQoKc3RhdGVfbWFwIDwtIG1hcF9kYXRhKCJzdGF0ZSIpCnN0YXRlX21hcApgYGAKCgojIyMjIEFubm95aW5nbHkgaXQgZG9lc24ndCBoYXZlIHRoZSBhYmJyZXZpYXRpb24gb2YgdGhlIFN0YXRlLCBvbmx5IHRoZSBmdWxsIG5hbWUgc28gSSBuZWVkIHRvIGFkZCB0aGF0IGluLiAgTHVja2lseSB0aGUgJ2RhdGFzZXRzJyBwYWNrYWdlIGFsc28gaGFzIGEgdmVjdG9yIG9mIFN0YXRlcyBuYW1lcyBhbmQgYWJicmV2aWF0aW9ucyBzbyBJIHNoYWxsIG1ha2UgYSB0aWJibGUgd2l0aCB0aGVtIGJvdGggaW4uCgoKYGBge3J9CnN0YXRlLmFiYgpgYGAKCmBgYHtyfQpzdGF0ZS5uYW1lCmBgYAoKYGBge3J9CnN0YXRlX2xpc3QgPC0gdGliYmxlKHN0YXRlID0gc3RhdGUuYWJiLCBzdGF0ZV9uYW1lID0gc3RhdGUubmFtZSkKc3RhdGVfbGlzdApgYGAKCgojIyMjIFRoZSBgc3RhdGVfbWFwYCBkYXRhZnJhbWUgaXMgaW4gbG93ZXIgY2FzZSBhbmQgaGFzIHRoZSBjb2x1bW4gbmFtZSAncmVnaW9uJy4gIEkgc2hhbGwgY2hhbmdlIHRoZSBgc3RhdGVfbGlzdGAgdGliYmxlIHRvIGJlIHRoZSBzYW1lIGZvcm1hdCBzbyB0aGV5IGNhbiBiZSBqb2luZWQgdG9nZXRoZXIuCgoKYGBge3J9CnN0YXRlX2xpc3QgPC0gdGliYmxlKHN0YXRlID0gc3RhdGUuYWJiLCByZWdpb24gPSB0b2xvd2VyKHN0YXRlLm5hbWUpKQpgYGAKCgojIyMjIEpvaW5nIGBzdGF0ZV9saXN0YCB0byBgZmlyZXNfc21hbGxgIGRhdGFzZXRzCgpgYGB7cn0KZmlyZXNfc3RhdGVzIDwtIGZpcmVzX3NtYWxsICU+JQogIGxlZnRfam9pbihzdGF0ZV9saXN0LCBieSA9ICJzdGF0ZSIpCgpmaXJlc19zdGF0ZXMKYGBgCgoKIyMjIyBDaGVja2luZyB0aGUgam9pbiBoYXMgd29ya2VkIGFuZCB0aGVyZSBhcmUgbm8gbWlzc2luZyB2YWx1ZXMuCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihpcy5uYShyZWdpb24pKQpgYGAKCgojIyMjIFRoZXJlIGRvZXMgc2VlbSB0byBiZSAyMiwxNDcgTkFzIGluIHRoZSAncmVnaW9uJyBjb2x1bW4gd2UganVzdCBtYWRlLiAgU2Nyb2xsaW5nIHRocm91Z2ggdGhlcmUgYXJlIDIgbWlzc2luZyBTdGF0ZXMgb2YgJ1BSJyBhbmQgJ0RDJyBpbiB0aGUgYHN0YXRlc19saXN0YCB0aWJibGUuCgojIyMjIEFmdGVyIHNvbWUgcXVpY2sgcmVzZWFyY2ggaXQgc2VlbXMgdGhhdCB0aGVyZSBhcmUgb25seSA1MCBTdGF0ZXMgaW4gdGhlIFVTLiBXYXNoaW5ndG9uIERDIGlzIHRlY2hpbmNhbGx5IG5vdCBjb3VudGVkIGFzIGEgc3RhdGUgYnV0IGFzIGEgRmVkZXJhbCBEaXN0cmljdCwgYXMgaXQgaXMgdGhlIHNlYXQgb2YgZ292ZXJubWVudCwgc28gdGhhdCB3YXMgd2h5IGl0IHdhc24ndCBpbmNsdWRlZCBpbiB0aGUgYFN0YXRlc2AgdGliYmxlIG9yaWdpbmFsbHkuICBQUiBpcyBQdWVydG8gUmljbyBhbmQgaXMgYWxzbyBub3QgYSBzdGF0ZSBidXQgdGhlIGxhcmdlc3QgVVMgdGVycml0b3J5IC4KCgojIyMjIEkgc2hhbGwgYWRkIERDIGFuZCBQUiBpbnRvIHRoZSBzdGF0ZV9saXN0IGFuZCByZS1qb2luIGl0LgoKYGBge3J9CiMgQWRkaW5nIDIgbmV3IHN0YXRlcwoKc3RhdGUuYWJiIDwtIGFwcGVuZChzdGF0ZS5hYmIsIGMoIkRDIiwgIlBSIikpCnN0YXRlLm5hbWUgPC0gYXBwZW5kKHN0YXRlLm5hbWUsIGMoIkRpc3RyaWN0IG9mIENvbHVtYmlhIiwgIlB1ZXJ0byBSaWNvIikpCgpzdGF0ZV9saXN0IDwtIHRpYmJsZShzdGF0ZSA9IHN0YXRlLmFiYiwgcmVnaW9uID0gdG9sb3dlcihzdGF0ZS5uYW1lKSkKYGBgCgoKYGBge3J9CiMgUmUtam9pbmcgdGliYmxlcwoKZmlyZXNfc3RhdGVzIDwtIGZpcmVzX3NtYWxsICU+JQogIGxlZnRfam9pbihzdGF0ZV9saXN0LCBieSA9ICJzdGF0ZSIpCmBgYAoKCmBgYHtyfQojIENoZWNraW5nIHRoZSBqb2luIGhhcyB3b3JrZWQgcHJvcGVybHkgYW5kIHRoZXJlIGFyZSBubyBOQXMKCmZpcmVzX3N0YXRlcyAlPiUKICBmaWx0ZXIoaXMubmEocmVnaW9uKSkKYGBgCgpgYGB7cn0KIyBDb2RlIGJlbG93IGJyaW5ncyB1cCBhICJ2ZWN0b3IgbWVtb3J5IGV4aGF1c3RlZCAobGltaXQgcmVhY2hlZD8pIiBlcnJvcgoKIyBmaXJlc19qb2luZWQgPC0gZmlyZXNfc3RhdGVzICU+JQojICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikKYGBgCgoKIyMjIyBUaGUgZGF0YSBzZXQgYW5kIGdlbyBpbmZvcm1hdGlvbiBpcyB0b28gYmlnIHRvIGpvaW4gc28gSSdtIGdvaW5nIHRvIGRvIGEgc3VtbWFyaXNlIGZpcnN0IHRvIGdldCB0aGUgbnVtYmVyIG9mIGZpcmVzIHBlciByZWdpb24gZmlyc3QuCgpgYGB7cn0KZmlyZXNfam9pbmVkIDwtIGZpcmVzX3N0YXRlcyAlPiUgCiAgICBzZWxlY3QocmVnaW9uKSAlPiUKICAgIGdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICAgIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKQpgYGAKCioqUmVzdWx0ISEgIE5vdyBkb2luZyBmaXJzdCBnZW8gc3BhdGlhbCB2aXN1YWxpc2F0aW9uKioKCgojIyMgVG90YWwgV2lsZGZpcmVzIHBlciBzdGF0ZSBmcm9tIDE5OTItMjAxNQoKYGBge3J9CmZpcmVzX2pvaW5lZCAlPiUgCiAgICBnZ3Bsb3QgKwogICAgKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IG51bV9maXJlcykpICsgCiAgICBnZW9tX3BvbHlnb24oKSArIAogICAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKyAKICAgIHNjYWxlX2ZpbGxfY29udGludW91cyhsb3cgPSAiZGFya2JsdWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gImRhcmtyZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTnVtYmVyIG9mIGZpcmVzIikgKyAKICAgIHRoZW1lX21hcCgpICsgCiAgICBjb29yZF9tYXAoIm1vbGx3ZWlkZSIpICsgCiAgICBnZ3RpdGxlKCJUb3RhbCBVUyBXaWxkZmlyZXMgZnJvbSAxOTkyLTIwMTUiKSArIAogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCiMgMy4gR2VvIFNwYXRpYWwgVmlzdWFsaXNhdGlvbnMKCiMjIyBUaGUgZGF0YXNldCBoYXMgYSBjYXVzZSBvZiBmaXJlIGNvbHVtbiBzbyBJIHNoYWxsIG5vdyBjcmVhdGUgc29tZSBjYXVzYXRpb24gcGxvdHMuCgoKIyMjIyBHZXR0aW5nIGxpc3Qgb2YgZmlyZSBjYXVzZXMKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZGlzdGluY3Qoc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgYXJyYW5nZSgtZGVzYyhzdGF0X2NhdXNlX2Rlc2NyKSkKYGBgCgoKIyMjIFRvdGFsIGZpcmUgYnkgY2F1c2UgaW4gdGFidWxhciBmb3JtCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBncm91cF9ieShzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbiAoKSkgJT4lCiAgYXJyYW5nZShkZXNjKG51bV9maXJlcykpCiAgCmBgYAoKIyMjIE51bWJlciBvZiBmaXJlcyBieSBzdGF0ZSBpbiB0YWJ1bGFyIGZvcm0KCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgc2VsZWN0KHJlZ2lvbikgJT4lCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBhcnJhbmdlKGRlc2MobnVtX2ZpcmVzKSkKYGBgCgoKIyMjIyBBcyB0aGUgY2F1c2UgbmVlZHMgdG8gYmUgZmlsdGVyZWQgYmVmb3JlIHRoZSBtYXAgam9pbiwgSSdtIGdvaW5nIHRvIGVpdGhlciBnb2luZyB0byBoYXZlIHRvIHJlcGVhdCBhIHdob2xlIGxvYWQgb2YgdGhlIHNhbWUgY29kZSBpbiBldmVyeSBzaW5nbGUgcGxvdCBvciB3cml0ZSBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBkbyBpdCBmb3IgbWUgd2l0aCwgc2F2aW5nIGEgbG90IG9mIHR5cGluZyEKCmBgYHtyfQojIEZ1bmN0aW9uIGZvciBwbG90dGluZyBjYXVzZSBvZiBmaXJlCgpjYXVzZSA8LSBmdW5jdGlvbihjYXVzZSkgewogIGZpcmVzX3N0YXRlcyAlPiUKICAgIGZpbHRlcihzdGF0X2NhdXNlX2Rlc2NyID09IGNhdXNlKSAlPiUKICAgIHNlbGVjdChyZWdpb24pICU+JQogICAgZ3JvdXBfYnkocmVnaW9uKSAlPiUKICAgIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuICgpKSAlPiUKICAgIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICAgIGdncGxvdCArCiAgICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gbnVtX2ZpcmVzKSkgKyAKICAgIGdlb21fcG9seWdvbigpICsgCiAgICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArIAogICAgc2NhbGVfZmlsbF9jb250aW51b3VzKGxvdyA9ICJkYXJrYmx1ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2ggPSAiZGFya3JlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJOdW1iZXIgb2YgZmlyZXMiKSArIAogICAgdGhlbWVfbWFwKCkgKyAKICAgIGNvb3JkX21hcCgibW9sbHdlaWRlIikgKyAKICAgIGdndGl0bGUocGFzdGUwKCJUb3RhbCBVUyBXaWxkZmlyZXMgY2F1c2VkIGJ5ICIsIGNhdXNlLCAiIGZyb20gMTk5Mi0yMDE1IikpICsgCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKfQpgYGAKCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgQXJzb24KCmBgYHtyfQpjYXVzZSgiQXJzb24iKQpgYGAKCioqQXJzb24gZG9lcyBzZWVtIG1vcmUgcHJldmFsZW50IGluIHRoZSBTRSBzdGF0ZXMgb2YgTWlzc2lzc2lwcGksIEdlb3JnaWEsIEFsYWJhbWEgYW5kIGFsc28gdGhlIHdlc3Rlcm4gc3RhdGUgb2YgQ2FsaWZvcm5pYS4qKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IENhbXBmaXJlCgpgYGB7cn0KY2F1c2UoIkNhbXBmaXJlIikKYGBgCgoqKkNhbXBmaXJlcyBhcmUgdGhlIG1vc3QgcHJldmFsZW50IGluIHRoZSBXZXN0ZXJuIHN0YXRlcyBvZiBPcmVnb24sIENhbGlmb3JuaWEgYW5kIEFyaXpvbmEuKioKCgojIyMgV2lsZGZpcmVzIGNhdXNlZCBieSBDaGlsZHJlbgoKYGBge3J9CmNhdXNlKCJDaGlsZHJlbiIpCmBgYAoKKipGaXJlcyBieSBjaGlsZHJlbiBhcmUgc3ByZWFkIGFib3V0IHRoZSBjb3VudHJ5LCBidXQgdGhlIG1vc3QgcHJldmFsZW50IHN0YXRlcyBhcmUgQ2FsaWZvcm5pYSBpbiB0aGUgV2VzdCwgQWxhYmFtYSBhbmQgU291dGggQ2Fyb2xpbmEgYW5kIE5ldyBKZXJzZXkgaW4gdGhlIGVhc3QuKioKCgojIyMgV2lsZGZpcmVzIGNhdXNlZCBieSBEZWJyaXMgQnVybmluZwoKYGBge3J9CmNhdXNlKCJEZWJyaXMgQnVybmluZyIpCmBgYAoKKipGaXJlcyBieSBidXJuaW5nIGRlYnJpcyBhcmUgbW9zdGx5IGluIHRoZSBzb3V0aGVybiB3YXJtZXIgc3RhdGVzIG9mIFRleGFzLCBHZW9yZ2lhIGFuZCBOb3J0aCBDYXJvbGluYS4qKgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgRXF1aW1lbnQgVXNlCgpgYGB7cn0KY2F1c2UoIkVxdWlwbWVudCBVc2UiKQpgYGAKCioqTW9zdCBvZiB0aGUgZmlyZXMgY2F1c2VkIGJ5IGVxdWlwbWVudCBzZWVtIHRvIGJlIGluIENhbGlmb3JuaWEqKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IEZpcmV3b3JrcwoKYGBge3J9CmNhdXNlKCJGaXJld29ya3MiKQpgYGAKCioqTW9zdCBvZiB0aGUgZmlyZXMgY2F1c2VkIGJ5IGZpcmV3b3JrcyBzZWVtIHRvIGJlIGluIHRoZSBub3J0aCBvZiB0aGUgY291bnRyeS4gIFByaW1hcmlseSBTb3V0aCBEYWtvdGEsIE1vbnRhbmEgYW5kIFdhc2hpbmd0b24gc3RhdGUuKioKCgojIyMgV2lsZGZpcmVzIGNhdXNlZCBieSBMaWdodG5pbmcKCmBgYHtyfQpjYXVzZSgiTGlnaHRuaW5nIikKYGBgCgoqKkFwYXJ0IGZyb20gYSBob3RzcG90IG9mIGxpZ2h0bmluZyBzdHJpa2VzIGluIEZsb3JpZGEsIHRoZSB2YXN0IG1ham9yaXR5IG9mIGZpcmVzIGNhdXNlZCBieSBsaWdodG5pbmcgYXJlIGluIHRoZSBXZXN0IG9mIHRoZSBjb3VudHJ5LiAgV2l0aCB0aGUgMyBtb3N0IGFmZmVjdGVkIHN0YXRlcyBiZWluZyBDYWxpZm9ybmlhLCBPcmVnb24gYW5kIEFyaXpvbmEuKioKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IE1pc2NlbGxpb3VzCgpgYGB7cn0KY2F1c2UoIk1pc2NlbGxhbmVvdXMiKQpgYGAKCioqVGhlcmUgc2VlbXMgdG8gYmUgcXVpdGUgYSBmZXcgbWlzY2VsbGFuZW91cyBjbGFzc2lmaWNhdGlvbnMgaW4gQ2FsaWZvcm5pYSwgVGV4YXMgYW5kIE5ldyBZb3JrLioqCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgTWlzc2luZy9VbmRlZmluZWQKCmBgYHtyfQpjYXVzZSgiTWlzc2luZy9VbmRlZmluZWQiKQpgYGAKCioqVGhlIHN0YXRlcyB3aXRoIHRoZSBtb3N0IG1pc3Npbmcgb3IgdW5kZWZpbmVkIGRhdGEgaXMgTm9ydGggYW5kIFNvdXRoIENhcm9saW5hLCBPa2xhaG9tYSBhbmQgQ2FsaWZvcm5pYS4qKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IFBvd2VybGluZQoKYGBge3J9CmNhdXNlKCJQb3dlcmxpbmUiKQpgYGAKCioqVGV4YXMgaGFzIHRoZSBsYXJnZXN0IGFtb3VudCBvZiB3aWxkZmlyZXMgY2F1c2VkIGJ5IHBvd2VybGluZXMuICBUaGlzIGlzIGxpa2VseSBkdWUgdG8gdGhlIHdhcm0gY2xpbWF0ZSBhbmQgdGhlIGxhcmdlIHByb3BvcnRpb24gb2YgdGhlIHN0YXRlIHRoYXQgaXMgZHJ5IGdyYXNzbGFuZHMgdXNlZCBmb3IgYWdyaWN1bHR1cmUuICgxKSAqKgoKKDEpIGh0dHBzOi8vdWsucmV1dGVycy5jb20vYXJ0aWNsZS91cy13aWxkZmlyZXMtdGV4YXMvdHJlZXMtYW5kLXBvd2VyLWxpbmVzLWNhdXNlZC1tYWpvci10ZXhhcy1maXJlLWlkVVNUUkU3OEo3NkEyMDExMDkyMAoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IFJhaWxyb2FkCgpgYGB7cn0KY2F1c2UoIlJhaWxyb2FkIikKYGBgCgoqKkJ5IGZhciBGbG9yaWRhIGhhcyB0aGUgbW9zdCB3aWxkZmlyZXMgY2F1c2VkIGJ5IHJhaWxyb2Fkcy4qKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IFNtb2tpbmcKCmBgYHtyfQpjYXVzZSgiU21va2luZyIpCmBgYAoKKipGaXJlcyBjYXVzZWQgYnkgc21va2luZyBzZWVtIHRvIGJlIHNwcmVhZCBhcm91bmQgdGhlIGNvdW50cnksIGJ1dCBtYWlubHkgb24gdGhlIGVhc3QgYW5kIHdlc3QgY29hc3RzLioqCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgU3RydWN0dXJlCgpgYGB7cn0KY2F1c2UoIlN0cnVjdHVyZSIpCmBgYAoKKipTb3V0aCBEYWtvdGEgaGFzIHRoZSBsYXJnZXN0IHByb3BvcnRpb24gb2YgZmlyZXMgY2F1c2VkIGJ5IHN0cnVjdHVyZXMuKioKCgoKIyMjIyBVbnN1cnByaXNpbmdseSB0aGUgc291dGhlcm4gc3RhdGVzIHNlZW0gdG8gaGF2ZSBtb3JlIG9jY3VyZW5jZXMgb2Ygd2lsZGlmcmUgaW4gZ2VuZXJhbCwgbm8gZG91YnQgZHVlIHRvIHRoZSB3YXJtZXIgY2xpbWF0ZSBhdCB0aGVpciBsYXRpdHVkZXMuICBBbHNvIHRoZSAxc3QgYW5kIDNyZCBzdGF0ZXMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2YgZmlyZXMgYXJlIGFsc28gdGhlIDIgbGFyZ2VzdCBTdGF0ZXMgYnkgc2l6ZS4gSG93ZXZlciB0aGUgMm5kIGhpZ2hlc3QgU3RhdGUgaXMgR2VvcmdpYSwgd2hpY2ggYWx0aG91Z2ggaXQgaXMgaW4gdGhlIFNvdXRoIG9mIHRoZSBjb3VudHJ5IGlzIG9ubHkgYW4gYXZlcmFnZSBzaXplZCBTdGF0ZS4gIFRoZXJlZm9yZSB0byBnZXQgYSBiZXR0ZXIgcGljdHVyZSBvZiB3aGF0IGlzIGdvaW5nIG9uIEknbSBnb2luZyB0byBsb29rIGF0IHRoZSBwcm9wb3J0aW9uIG9mIGZpcmVzIG9jY3VyaW5nIGJ5IHNxdWFyZSBtaWxlIGJ5IG5vcm1hbGlzaW5nIHRoZSBTdGF0ZSBzaXplLgoKIyMjIyBUaGUgYGRhdGFzZXRgIHBhY2thZ2UgYWxzbyBoYXMgdGhlIGFyZWEgaW4gc3F1YXJlIG1pbGVzIG9mIGVhY2ggc3RhdGUgaW5jbHVkZWQgaW4gdGhlIGBzdGF0ZS5hcmVhYCB2ZWN0b3IuCgpgYGB7cn0Kc3RhdGUuYXJlYQpgYGAKCmBgYHtyfQpsZW5ndGgoc3RhdGUuYXJlYSkKYGBgCgojIyMjIEFubm95aW5nbHkgaXQgYWxzbyBvbmx5IGhhcyA1MCBzdGF0ZXMgbm90IDUyIHNvIEkgd2lsbCBuZWVkIHRvIGFkZCBpbiBEQyBhbmQgUFIgYmFjayBpbi4gIAoKKEFyZWEgZmlndXJlcyBvYnRhaW5lZCBmcm9tIFdpa2lwZWRpYSkKCkRDID0gNjggbWlsZXNeMgpQUiA9IDM1MTUgbWlsZXNeMgoKCmBgYHtyfQojIFRvIG1ha2UgbXkgbGlmZSBlYXNpZXIgSSdtIGdvaW5nIHRvIHJlbW92ZSB0aGUgc3RhdGUuYWJiIGFuZCAubmFtZSBmaWxlcyBhbmQgbWFrZSB0aGUgdGliYmxlIGFnYWluLCBhZGRpbmcgaW4gdGhlIGxhbmQgYXJlYSBmaWd1cmVzIGF0IHRoZSBzYW1lIHRpbWUgdG8gbWFrZSBzdXJlIHRoZXkgYXJlIGluIHRoZSBjb3JyZWN0IG9yZGVyLgoKcm0oc3RhdGUuYWJiKQpybShzdGF0ZS5uYW1lKQoKc3RhdGUuYWJiIDwtIGFwcGVuZChzdGF0ZS5hYmIsIGMoIkRDIiwgIlBSIikpCnN0YXRlLm5hbWUgPC0gYXBwZW5kKHN0YXRlLm5hbWUsIGMoIkRpc3RyaWN0IG9mIENvbHVtYmlhIiwgIlB1ZXJ0byBSaWNvIikpCnN0YXRlLmFyZWEgPC0gYXBwZW5kKHN0YXRlLmFyZWEsIGMoIjY4IiwgIjM1MTUiKSkKCnN0YXRlX2xpc3QgPC0gdGliYmxlKHN0YXRlID0gc3RhdGUuYWJiLCByZWdpb24gPSB0b2xvd2VyKHN0YXRlLm5hbWUpLCBhcmVhID0gYXMubnVtZXJpYyhzdGF0ZS5hcmVhKSkKYGBgCgpgYGB7cn0KIyBSZS1qb2luaW5nIHRpYmJsZXMKCmZpcmVzX3N0YXRlcyA8LSBmaXJlc19zbWFsbCAlPiUKICBsZWZ0X2pvaW4oc3RhdGVfbGlzdCwgYnkgPSAic3RhdGUiKQpgYGAKCgojIyMgTm9ybWFsaXNpbmcgU3RhdGVzIGFyZWEgc2l6ZXMKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgYXJlYSkgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBhcmVhKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBtdXRhdGUoZmlyZXNfc3FtaWxlID0gbnVtX2ZpcmVzIC8gYXJlYSkgJT4lCiAgYXJyYW5nZShkZXNjKGZpcmVzX3NxbWlsZSkpCmBgYAoKIyMjIyBUaGlzIHRhYmxlIHNob3dzIFB1ZXJ0byBSaWNvIGhhcyB0aGUgaGlnaGVzdCBwcm9wb3J0aW9uIG9mIGZpcmVzIGNvbXBhcmVkIHRvIGl0cyBzaXplLCBmb2xsb3dlZCBieSBOZXcgSmVyc2V5IGluIHRoZSBORSBvZiB0aGUgY291bnRyeSBhbmQgZmluYWxseSBieSB0aGUgU3RhdGVzIGluIHRoZSBTRSBvZiB0aGUgY291bnRyeS4KCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChyZWdpb24sIGFyZWEpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgYXJlYSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgbXV0YXRlKGZpcmVzX3NxbWlsZSA9IG51bV9maXJlcyAvIGFyZWEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBmaXJlc19zcW1pbGUpKSArIAogIGdlb21fcG9seWdvbigpICsgCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKyAKICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lID0gIkZpcmUgcGVyIFNxIE1pbGUiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICB0aGVtZV9tYXAoKSArIAogIGNvb3JkX21hcCgibW9sbHdlaWRlIikgKyAKICBnZ3RpdGxlKHBhc3RlMCgiVG90YWwgVVMgV2lsZGZpcmVzIHBlciBTcXVhcmUgTWlsZSBmcm9tIDE5OTItMjAxNSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCioqUHVlcnRvIFJpY28gaXMgbm90IHNob3duIG9uIHRoaXMgbWFwLCBidXQgdmlzdWFsbHkgd2UgY2FuIHNlZSB0aGUgZGF0YSBmb3IgdGhlIG90aGVyIDUxIGVudHJpZXMsIGFuZCB0aGUgc291dGggZWFzdGVybiBzdGF0ZXMgc3RpbGwgaGF2ZSB0aGUgaGlnaGVzdCBwcm9wb3J0aW9uIG9mIHdpbGRmaXJlcy4gIEludGVyZXN0aW5nbHkgTmV3IEplcnNleSBhbHNvIHNob3dzIGhhcyBhIGhvdHNwb3QgaW4gdGhlIE5FIG9mIHRoZSBjb3VudHJ5LioqCgoKIyMjIERvIGNhdXNlcyBjaGFuZ2Ugb3ZlciB0aW1lPwoKCiMjIyMgU3BsaXR0aW5nIGNhdXNlcyBpbnRvIDIgZ3JvdXAgZm9yIGxlZ2liaWxpdHkuIAoKIyMjIyBUaGUgZmlyc3QgZ3JvdXAgaXMgZm9yIGRpcmVjdGx5IG1hbiBjcmVhdGVkIGZpcmVzLgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBzZWxlY3Qoc3RhdF9jYXVzZV9kZXNjciwgZmlyZV95ZWFyKSAlPiUKICBncm91cF9ieShmaXJlX3llYXIsIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIGZpbHRlcihzdGF0X2NhdXNlX2Rlc2NyID09ICJBcnNvbiIgfCBzdGF0X2NhdXNlX2Rlc2NyID09ICJDYW1wZmlyZSIgfAogICAgICAgICAgIHN0YXRfY2F1c2VfZGVzY3IgPT0gIkNoaWxkcmVuIiB8IHN0YXRfY2F1c2VfZGVzY3IgPT0gIkVxdWlwbWVudCBVc2UiIHwKICAgICAgICAgICBzdGF0X2NhdXNlX2Rlc2NyID09ICJGaXJld29ya3MiIHwgc3RhdF9jYXVzZV9kZXNjciA9PSAiU21va2luZyIpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpICU+JQogIGdncGxvdCArCiAgYWVzKHggPSBmaXJlX3llYXIsIHkgPSBudW1fZmlyZXMsIGNvbG91ciA9IHN0YXRfY2F1c2VfZGVzY3IpICsKICBnZW9tX2xpbmUoKQpgYGAKCioqVGhlIDIgbGFyZ2UgcGVha3MgaW4gQXJzb24gYXJlIG9idmlvdXMgaW4gMTk5OSBhbmQgMjAwNi4gVGhlcmUgd2FzIGEgbGFyZ2UgaGVhdHdhdmUgaW4gMjAwNiwgYnV0IEknbSBub3Qgc3VyZSB3aHkgdGhpcyB3b3VsZCByZXN1bHQgaW4gYW4gaW5jcmVhc2UgaW4gYXJzb24uICBVbmxlc3MgdGhpcyB3YXMganVzdCBkdWUgdG8gdGhlIGRyeSBncm91bmQgY3JlYXRpbmcgZXh0cmEgZnVlbCB0byBhaWQgdGhlIHNwcmVhZCBvZiBmaXJlcyB0aGF0IHdvdWxkIGhhdmUgbm9ybWFsbHkgbm90IHJlc3VsdGVkIGluIGEgbGFyZ2Ugc2NhbGUgZmlyZS4gIFRoaXMgbWF5IGFsc28gYmUgdGhlIHNhbWUgcmVhc29uIHRoYXQgdGhlcmUgaXMgYWxzbyBhbm90aGVyIHBlYWsgaW4gMjAwNiBmb3IgRXF1aXBtZW50IFVzZS4gIEFyc29uIGhvd2V2ZXIgZG9lcyBsb29rIHRvIGJlIGRlY3JlYXNpbmcgc2luY2UgMjAwNi4qKgoKCiMjIyMgQW5kIHRoaXMgb25lIGZvciBuYXR1cmFsIG9jY3VyaW5nIGZpcmVzLgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBzZWxlY3Qoc3RhdF9jYXVzZV9kZXNjciwgZmlyZV95ZWFyKSAlPiUKICBncm91cF9ieShmaXJlX3llYXIsIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIGZpbHRlcihzdGF0X2NhdXNlX2Rlc2NyID09ICJEZWJyaXMgQnVybmluZyIgfCBzdGF0X2NhdXNlX2Rlc2NyID09ICJMaWdodG5pbmciIHwKICAgICAgICAgICBzdGF0X2NhdXNlX2Rlc2NyID09ICJNaXNjZWxsYW5lb3VzIiB8IHN0YXRfY2F1c2VfZGVzY3IgPT0gCiAgICAgICAgICAgIk1pc3NpbmcvVW5kZWZpbmVkIiB8IHN0YXRfY2F1c2VfZGVzY3IgPT0gIlBvd2VybGluZSIgfCAKICAgICAgICAgICBzdGF0X2NhdXNlX2Rlc2NyID09ICJSYWlscm9hZCIgfCBzdGF0X2NhdXNlX2Rlc2NyID09ICJTdHJ1Y3R1cmUiKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBnZ3Bsb3QgKwogIGFlcyh4ID0gZmlyZV95ZWFyLCB5ID0gbnVtX2ZpcmVzLCBjb2xvdXIgPSBzdGF0X2NhdXNlX2Rlc2NyKSArCiAgZ2VvbV9saW5lKCkKYGBgCgoqKlNpbWlsYXIgcGVha3MgY2FuIGJlIHNlZW4gaW4gRGVicmlzLCBNaXNjZWxsYW5lb3VzIGFuZCBsaWdodG5pbmcgaW4gdGhlIGhlYXR3YXZlIG9mIDIwMDYgdGhhdCBsZWZ0IHRoZSBncm91bmQgdmVyeSBkcnkuICBUaGVyZSBhcmUgcGVha3MgZnJvbSAxOTk3IHRvIDIwMDMgaW4gZGVicmlzLCBtaXNjZWxsYW5lb3VzIGFuZCBsaWdodGVuaW5nLCBidXQgYWxzbyBhIHRyb3VnaCBpbiBtaXNzaW5nL3VuZGVmaW5lZCwgc28gdGhpcyBpcyBsaWtlbHkgdG8gYmUgZHVlIHRvIG1vcmUgYWNjdXJhdGUgY2xhc3NpZmljYXRpb24gb2YgZmlyZXMgYW5kIG5vdCB1c2luZyB0aGUgbWlzc2luZy91bmRlZmluZWQgY2F0ZWdvcnkgYXMgbXVjaC4qKgoKCgojIyMgRGlmZmVyZW5jZSBpbiBjYXVzZXMgYmV0d2VlbiBzdGF0ZXMKCgpgYGB7cn0Kc3RhdGVfbWFwX3NvdXRoZXJuIDwtIHN0YXRlX21hcCAlPiUKICBmaWx0ZXIocmVnaW9uID09ICJmbG9yaWRhIiB8IHJlZ2lvbiA9PSAiZ2VvcmdpYSIgfCByZWdpb24gPT0gImFsYWJhbWEiIHwKICAgICAgICAgICByZWdpb24gPT0gIm1pc3Npc3NpcHBpIiB8IHJlZ2lvbiA9PSAic291dGggY2Fyb2xpbmEiIHwgCiAgICAgICAgICAgcmVnaW9uID09ICJub3J0aCBjYXJvbGluYSIgfCByZWdpb24gPT0gInRlbm5lc3NlZSIgfCAKICAgICAgICAgICByZWdpb24gPT0gImFya2Fuc2FzIiB8IHJlZ2lvbiA9PSAibG91aXNpYW5hIikKYGBgCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBmaWx0ZXIoZmlyZV95ZWFyID09ICIxOTkyIiB8IGZpcmVfeWVhciA9PSAiMTk5MyIgfCBmaXJlX3llYXIgPT0gIjE5OTQiIHwKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjE5OTUiKSAlPiUKICBmaWx0ZXIocmVnaW9uID09ICJmbG9yaWRhIiB8IHJlZ2lvbiA9PSAiZ2VvcmdpYSIgfCByZWdpb24gPT0gImFsYWJhbWEiIHwKICAgICAgICAgICByZWdpb24gPT0gIm1pc3Npc3NpcHBpIiB8IHJlZ2lvbiA9PSAic291dGggY2Fyb2xpbmEiIHwgCiAgICAgICAgICAgcmVnaW9uID09ICJub3J0aCBjYXJvbGluYSIgfCByZWdpb24gPT0gInRlbm5lc3NlZSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAiYXJrYW5zYXMiIHwgcmVnaW9uID09ICJsb3Vpc2lhbmEiKSAlPiUKICBzZWxlY3QocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBncm91cF9ieShyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZSA9IG4oKSkgJT4lCiAgdG9wX24oMSkgJT4lCiAgcmlnaHRfam9pbihzdGF0ZV9tYXBfc291dGhlcm4sIGJ5ID0gInJlZ2lvbiIpICU+JQogIGdncGxvdCArCiAgKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IHN0YXRfY2F1c2VfZGVzY3IpKSArIAogIGdlb21fcG9seWdvbigpICsgCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKyAKICB0aGVtZV9tYXAoKSArIAogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiQ2F1c2Ugb2YgRmlyZXMiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJUb3RhbCBVUyBXaWxkZmlyZXMgbWFpbiBjYXVzZSBmcm9tIDE5OTItMTk5NSIpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGZpcmVfeWVhciA9PSAiMTk5NiIgfCBmaXJlX3llYXIgPT0gIjE5OTciIHwgZmlyZV95ZWFyID09ICIxOTk4IiB8CiAgICAgICAgICAgZmlyZV95ZWFyID09ICIxOTk5IikgJT4lCiAgZmlsdGVyKHJlZ2lvbiA9PSAiZmxvcmlkYSIgfCByZWdpb24gPT0gImdlb3JnaWEiIHwgcmVnaW9uID09ICJhbGFiYW1hIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJtaXNzaXNzaXBwaSIgfCByZWdpb24gPT0gInNvdXRoIGNhcm9saW5hIiB8IAogICAgICAgICAgIHJlZ2lvbiA9PSAibm9ydGggY2Fyb2xpbmEiIHwgcmVnaW9uID09ICJ0ZW5uZXNzZWUiIHwKICAgICAgICAgICByZWdpb24gPT0gImFya2Fuc2FzIiB8IHJlZ2lvbiA9PSAibG91aXNpYW5hIikgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwX3NvdXRoZXJuLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBzdGF0X2NhdXNlX2Rlc2NyKSkgKyAKICBnZW9tX3BvbHlnb24oKSArIAogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsgCiAgdGhlbWVfbWFwKCkgKyAKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIkNhdXNlIG9mIEZpcmVzIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiVG90YWwgVVMgV2lsZGZpcmVzIG1haW4gY2F1c2UgZnJvbSAxOTk2LTE5OTkiKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMDAiIHwgZmlyZV95ZWFyID09ICIyMDAxIiB8IGZpcmVfeWVhciA9PSAiMjAwMiIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAwMyIpICU+JQogIGZpbHRlcihyZWdpb24gPT0gImZsb3JpZGEiIHwgcmVnaW9uID09ICJnZW9yZ2lhIiB8IHJlZ2lvbiA9PSAiYWxhYmFtYSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAibWlzc2lzc2lwcGkiIHwgcmVnaW9uID09ICJzb3V0aCBjYXJvbGluYSIgfCAKICAgICAgICAgICByZWdpb24gPT0gIm5vcnRoIGNhcm9saW5hIiB8IHJlZ2lvbiA9PSAidGVubmVzc2VlIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJhcmthbnNhcyIgfCByZWdpb24gPT0gImxvdWlzaWFuYSIpICU+JQogIHNlbGVjdChyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcF9zb3V0aGVybiwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gc3RhdF9jYXVzZV9kZXNjcikpICsgCiAgZ2VvbV9wb2x5Z29uKCkgKyAKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArIAogIHRoZW1lX21hcCgpICsgCiAgc2NhbGVfZmlsbF9icmV3ZXIobmFtZSA9ICJDYXVzZSBvZiBGaXJlcyIsIHBhbGV0dGUgPSAiUHVCdUduIikgKwogIGdndGl0bGUoIlRvdGFsIFVTIFdpbGRmaXJlcyBtYWluIGNhdXNlIGZyb20gMjAwMC0yMDAzIikgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBmaWx0ZXIoZmlyZV95ZWFyID09ICIyMDA0IiB8IGZpcmVfeWVhciA9PSAiMjAwNSIgfCBmaXJlX3llYXIgPT0gIjIwMDYiIHwKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjIwMDciKSAlPiUKICBmaWx0ZXIocmVnaW9uID09ICJmbG9yaWRhIiB8IHJlZ2lvbiA9PSAiZ2VvcmdpYSIgfCByZWdpb24gPT0gImFsYWJhbWEiIHwKICAgICAgICAgICByZWdpb24gPT0gIm1pc3Npc3NpcHBpIiB8IHJlZ2lvbiA9PSAic291dGggY2Fyb2xpbmEiIHwgCiAgICAgICAgICAgcmVnaW9uID09ICJub3J0aCBjYXJvbGluYSIgfCByZWdpb24gPT0gInRlbm5lc3NlZSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAiYXJrYW5zYXMiIHwgcmVnaW9uID09ICJsb3Vpc2lhbmEiKSAlPiUKICBzZWxlY3QocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBncm91cF9ieShyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZSA9IG4oKSkgJT4lCiAgdG9wX24oMSkgJT4lCiAgcmlnaHRfam9pbihzdGF0ZV9tYXBfc291dGhlcm4sIGJ5ID0gInJlZ2lvbiIpICU+JQogIGdncGxvdCArCiAgKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IHN0YXRfY2F1c2VfZGVzY3IpKSArIAogIGdlb21fcG9seWdvbigpICsgCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKyAKICB0aGVtZV9tYXAoKSArIAogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiQ2F1c2Ugb2YgRmlyZXMiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJUb3RhbCBVUyBXaWxkZmlyZXMgbWFpbiBjYXVzZSBmcm9tIDIwMDQtMjAwNyIpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMDgiIHwgZmlyZV95ZWFyID09ICIyMDA5IiB8IGZpcmVfeWVhciA9PSAiMjAxMCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAxMSIpICU+JQogIGZpbHRlcihyZWdpb24gPT0gImZsb3JpZGEiIHwgcmVnaW9uID09ICJnZW9yZ2lhIiB8IHJlZ2lvbiA9PSAiYWxhYmFtYSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAibWlzc2lzc2lwcGkiIHwgcmVnaW9uID09ICJzb3V0aCBjYXJvbGluYSIgfCAKICAgICAgICAgICByZWdpb24gPT0gIm5vcnRoIGNhcm9saW5hIiB8IHJlZ2lvbiA9PSAidGVubmVzc2VlIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJhcmthbnNhcyIgfCByZWdpb24gPT0gImxvdWlzaWFuYSIpICU+JQogIHNlbGVjdChyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcF9zb3V0aGVybiwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gc3RhdF9jYXVzZV9kZXNjcikpICsgCiAgZ2VvbV9wb2x5Z29uKCkgKyAKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArIAogIHRoZW1lX21hcCgpICsgCiAgc2NhbGVfZmlsbF9icmV3ZXIobmFtZSA9ICJDYXVzZSBvZiBGaXJlcyIsIHBhbGV0dGUgPSAiUHVCdUduIikgKwogIGdndGl0bGUoIlRvdGFsIFVTIFdpbGRmaXJlcyBtYWluIGNhdXNlIGZyb20gMjAwOC0yMDExIikgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGZpcmVfeWVhciA9PSAiMjAxMiIgfCBmaXJlX3llYXIgPT0gIjIwMTMiIHwgZmlyZV95ZWFyID09ICIyMDE0IiB8CiAgICAgICAgICAgZmlyZV95ZWFyID09ICIyMDE1IikgJT4lCiAgZmlsdGVyKHJlZ2lvbiA9PSAiZmxvcmlkYSIgfCByZWdpb24gPT0gImdlb3JnaWEiIHwgcmVnaW9uID09ICJhbGFiYW1hIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJtaXNzaXNzaXBwaSIgfCByZWdpb24gPT0gInNvdXRoIGNhcm9saW5hIiB8IAogICAgICAgICAgIHJlZ2lvbiA9PSAibm9ydGggY2Fyb2xpbmEiIHwgcmVnaW9uID09ICJ0ZW5uZXNzZWUiIHwKICAgICAgICAgICByZWdpb24gPT0gImFya2Fuc2FzIiB8IHJlZ2lvbiA9PSAibG91aXNpYW5hIikgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwX3NvdXRoZXJuLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBzdGF0X2NhdXNlX2Rlc2NyKSkgKyAKICBnZW9tX3BvbHlnb24oKSArIAogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsgCiAgdGhlbWVfbWFwKCkgKyAKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIkNhdXNlIG9mIEZpcmVzIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiVG90YWwgVVMgV2lsZGZpcmVzIG1haW4gY2F1c2UgZnJvbSAyMDEyLTIwMTUiKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCioqTG9va2luZyBhdCB0aGVzZSB0cmVuZHMgc29tZSBpbnRlcmVzdGluZyBpbnNpZ2h0cyBjYW4gYmUgc2Vlbi4gIEZvciB0aGUgY29tYmluZWQgeWVhcnMgZGF0YSBGbG9yaWRhIHN0YW5kcyBvdXQgYXMgaGF2aW5nIHJhaWxyb2FkIGFzIGl0cyBtYWluIGNhdXNlIG9mIHdpbGRmaXJlLCBidXQgZnJvbSB0aGUgYWJvdmUgcGxvdHMgaXQgY2FuIGJlIHNlZW4gdGhhdCB0aGVzZSByYWlscm9hZCBmaXJlcyBhcmUgb25seSB0aGUgbWFpbiBjYXVzZSB1cCB0byB0aGUgNCB5ZWFybHkgcGVyaW9kIGVuZGluZyBpbiAyMDAzIGFuZCB0aGVuIHRoZSBtYWluIGNhdXNlIGNoYW5nZXMgdG8gbGlnaHRuaW5nIHVudGlsIHRoZSBlbmQgb2YgdGhlIGNvbGxlY3Rpb24gcGVyaW9kIGluIDIwMTUuICBTaW1pbGFybHkgYXJzb24gc2VlbSByZWFzb25hYmx5IHBvcHVsYXIgaW4gdGhlIHNvdXRoZXJuIHN0YXRlcyB1bnRpbCAyMDA3LCB3aGVuIGl0IG5vIGxvbmdlciBhcHBlYXJzIGFzIHRoZSBtb3N0IGNvbW1vbiBjYXVzZSBvZiB3aWxkZmlyZS4gIFRoaXMgZG93bndhcmQgdHJlbmQgd2FzIGFsc28gbm90ZWQgZWFybGllciBpbiB0aGUgb3ZlcmFsbCBjYXVzYXRpb24gcGxvdHMgZm9yIGFsbCBzdGF0ZXMqKgoKCgojIyMgQ29ycmVsYXRpb24gYmV0d2VlbiBzdGF0ZXMgYW5kIGZpcmUgc2l6ZQoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBzZWxlY3QocmVnaW9uLCBmaXJlX3NpemVfY2xhc3MpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZmlyZV9zaXplX2NsYXNzKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBmaXJlX3NpemVfY2xhc3MpKSArCiAgZ2VvbV9wb2x5Z29uKCkgKwogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsKICB0aGVtZV9tYXAoKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIobmFtZSA9ICJGaXJlIFNpemUgQ2xhc3MiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJNb3N0IGNvbW1vbiB3aWxkZmlyZSBzaXplIHBlciBTdGF0ZSAxOTkyLTIwMTUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgZmlyZV9zaXplX2NsYXNzKSAlPiUKICBmaWx0ZXIoZmlyZV9zaXplX2NsYXNzID09ICJHIikgJT4lCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBudW1fZmlyZSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lID0gIk51bWJlciBvZiBGaXJlcyIsIHBhbGV0dGUgPSAiUHVCdUduIikgKwogIGdndGl0bGUoIk51bWJlciBvZiBsYXJnZSBjbGFzcyBHIGZpcmVzIHBlciBTdGF0ZSAxOTkyLTIwMTUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKKipGcm9tIHRoZSBwbG90cyB3ZSBjYW4gc2VlIHRoYXQgdGhlIFdlc3Rlcm4gc3RhdGVzIGhhdmUgdGhlIG1vc3Qgc21hbGwgZmlyZXMgYW5kIGFsc28gdGhlIG1vc3QgbGFyZ2UgZmlyZXMhICBOb3QgZW50aXJlbHkgdGhlIG1vc3QgaGVscGZ1bCBwbG90cy4uLioqCgoKCiMjIyBBcmUgZmlyZXMgbW9yZSBwcmV2YWxlbnQgaW4gY2VydGFpbiBtb250aHMgZm9yIGluZGl2aWR1YWwgc3RhdGVzCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjE5OTIiIHwgZmlyZV95ZWFyID09ICIxOTkzIiB8IGZpcmVfeWVhciA9PSAiMTk5NCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMTk5NSIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAxOTkyLTE5OTUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjE5OTYiIHwgZmlyZV95ZWFyID09ICIxOTk3IiB8IGZpcmVfeWVhciA9PSAiMTk5OCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMTk5OSIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAxOTk2LTE5OTkiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGZpcmVfeWVhciA9PSAiMjAwMCIgfCBmaXJlX3llYXIgPT0gIjIwMDEiIHwgZmlyZV95ZWFyID09ICIyMDAyIiB8CiAgICAgICAgICAgZmlyZV95ZWFyID09ICIyMDAzIikgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBkaXNjb3ZlcnlfbW95KSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBkaXNjb3ZlcnlfbW95KSkgKwogIGdlb21fcG9seWdvbigpICsKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArCiAgdGhlbWVfbWFwKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiTW9udGhzIG9mIFllYXIiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJNb250aCB3aXRoIG1vc3QgZmlyZXMgcGVyIFN0YXRlIDIwMDAtMjAwMyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBmaWx0ZXIoZmlyZV95ZWFyID09ICIyMDA0IiB8IGZpcmVfeWVhciA9PSAiMjAwNSIgfCBmaXJlX3llYXIgPT0gIjIwMDYiIHwKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjIwMDciKSAlPiUKICBzZWxlY3QocmVnaW9uLCBkaXNjb3ZlcnlfbW95KSAlPiUKICBncm91cF9ieShyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZSA9IG4oKSkgJT4lCiAgdG9wX24oMSkgJT4lCiAgcmlnaHRfam9pbihzdGF0ZV9tYXAsIGJ5ID0gInJlZ2lvbiIpICU+JQogIGdncGxvdCArCiAgKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGRpc2NvdmVyeV9tb3kpKSArCiAgZ2VvbV9wb2x5Z29uKCkgKwogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsKICB0aGVtZV9tYXAoKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIobmFtZSA9ICJNb250aHMgb2YgWWVhciIsIHBhbGV0dGUgPSAiUHVCdUduIikgKwogIGdndGl0bGUoIk1vbnRoIHdpdGggbW9zdCBmaXJlcyBwZXIgU3RhdGUgMjAwNC0yMDA3IikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMDgiIHwgZmlyZV95ZWFyID09ICIyMDA5IiB8IGZpcmVfeWVhciA9PSAiMjAxMCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAxMSIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAyMDA4LTIwMTEiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGZpcmVfeWVhciA9PSAiMjAxMiIgfCBmaXJlX3llYXIgPT0gIjIwMTMiIHwgZmlyZV95ZWFyID09ICIyMDE0IiB8CiAgICAgICAgICAgZmlyZV95ZWFyID09ICIyMDE1IikgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBkaXNjb3ZlcnlfbW95KSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBkaXNjb3ZlcnlfbW95KSkgKwogIGdlb21fcG9seWdvbigpICsKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArCiAgdGhlbWVfbWFwKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiTW9udGhzIG9mIFllYXIiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJNb250aCB3aXRoIG1vc3QgZmlyZXMgcGVyIFN0YXRlIDIwMTItMjAxNSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBmaWx0ZXIoZmlyZV95ZWFyID09ICIyMDEwIiB8IGZpcmVfeWVhciA9PSAiMjAxMSIgfCBmaXJlX3llYXIgPT0gIjIwMTIiIHwKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjIwMTMiIHwgZmlyZV95ZWFyID09ICIyMDE0IiB8IGZpcmVfeWVhciA9PSAiMjAxNSIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIGluIHBlciBTdGF0ZSAyMDEwLTIwMTUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCioqVGhlIGFib3ZlIHBsb3RzIGFyZSBxdWl0ZSBpbnRlcmVzdGluZy4gIFRoZSBtb250aHMgb2YgdGhlIHllYXIgdGhhdCBoYXZlIHRoZSBtb3N0IHNlZW1zIHRvIHdpZGVseSBjaGFuZ2UgaW4gY2VydGFpbiBzdGF0ZS4gIE1haW5seSB0aGUgZWFzdCBoYWxmIG9mIHRoZSBjb3VudHJ5IGhhdmUgdGhlIG1vc3QgZmlyZXMgaW4gdGhlIFNwcmluZyAoRmViLU1heSkgYW5kIHRoZSB3ZXN0ZXJuIHBhcnQgb2YgdGhlIGNvdW50cnkgaGF2ZSB0aGUgbW9zdCBmaXJlcyBsYXRlciBvbiBpbiBTdW1tZXIgYW5kIEZhbGwgKEp1bi1PY3QpLiAgVGhlcmUgYXJlIGhvd2V2ZXIgYSBmZXcgZXhjZXB0aW9ucyB0aGF0IGNhbiBiZSBzZWVuIGluIHRoZSAyMDA0LTIwMDcgYW5kIDIwMDgtMjAxMSBkYXRhIFRleGFzIGhhcyB0aGUgbW9zdCBmaXJlcyBpbiBKYW51YXJ5LiAgRmxvcmlkYSBhbHNvIG1vc3RseSBjb25mb3JtZWQgdG8gdGhlIEVhc3QvV2VzdCBzcGxpdCB3aXRoIHRoZSBtYWpvcml0eSBvZiBpdHMgd29yc3QgbW9udGhzIGZvciBmaXJlcyB0YWtpbmcgcGxhY2UgaW4gTWFyY2ggb3IgQXByaWwgdXAgdW50aWwgMjAwNywgdGhlbiB0aGUgbW9zdCBjb21tb24gbW9udGggbW92ZXMgbGF0ZXIgaW50byBKdW5lIGFuZCBKdWx5IGZvciB0aGUgcmVzdCBvZiB0aGUgcmVwb3J0aW5nIHBlcmlvZCB1bnRpbCAyMDE1LiBUaGlzIG1heSBoYXZlIHRvIGR1ZSB3aXRoIG1haW4gY2F1c2Ugb2YgZmlyZXMgaW4gRmxvcmlkYSBjaGFuZ2luZyBmcm9tIHJhaWxyb2FkIHRvIGxpZ2h0bmluZyByZWxhdGVkIGFib3V0IHRoZSBzYW1lIHRpbWUsIGFzIHdlIG5vdGVkIGVhcmxpZXIgb24gd2hlbiBsb29raW5nIGF0IGNhdXNhdGlvbi4gIEFzIEp1bHkgaXMgdGhlIG1haW4gbW9udGggZm9yIHRyb3BpY2FsIHN0b3JtcyBhbmQgbGlnaHRuaW5nIGluIEZsb3JpZGEgdGhpcyBpcyBhIHBvc3NpYmxlIGNhdXNlIGZvciB0aGUgaGlnaGVzdCBtb250aCBiZWNvbWluZyBsYXRlciBpbiB0aGUgeWVhciB0aGFuIGJlZm9yZS4gKDIpKioKCgooMikgaHR0cHM6Ly93d3cud2VhdGhlci5nb3YvbWxiL2ZsX2xpZ2h0bmluZ19jbGltbwoKCg==